Skip to content

Commit c1ebc05

Browse files
authored
[ new ] semantic highlighting in REPL & holes (#1836)
1 parent 82796b3 commit c1ebc05

File tree

33 files changed

+1094
-656
lines changed

33 files changed

+1094
-656
lines changed

idris2api.ipkg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ modules =
199199
TTImp.ProcessType,
200200
TTImp.Reflect,
201201
TTImp.TTImp,
202+
TTImp.TTImp.Functor,
202203
TTImp.Unelab,
203204
TTImp.Utils,
204205
TTImp.WithClause,

src/Core/Metadata.idr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,21 @@ nameTypeDecoration Func = Function
3434
nameTypeDecoration (DataCon _ _) = Data
3535
nameTypeDecoration (TyCon _ _ ) = Typ
3636

37+
export
38+
defDecoration : Def -> Maybe Decoration
39+
defDecoration None = Nothing
40+
defDecoration (PMDef {}) = Just Function
41+
defDecoration (ExternDef {}) = Just Function
42+
defDecoration (ForeignDef {}) = Just Function
43+
defDecoration (Builtin {}) = Just Function
44+
defDecoration (DCon {}) = Just Data
45+
defDecoration (TCon {}) = Just Typ
46+
defDecoration (Hole {}) = Just Function
47+
defDecoration (BySearch {}) = Nothing
48+
defDecoration (Guess {}) = Nothing
49+
defDecoration ImpBind = Just Bound
50+
defDecoration Delayed = Nothing
51+
3752
public export
3853
ASemanticDecoration : Type
3954
ASemanticDecoration = (NonEmptyFC, Decoration, Maybe Name)

src/Core/TT.idr

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ isCon (DataCon t a) = Just (t, a)
2929
isCon (TyCon t a) = Just (t, a)
3030
isCon _ = Nothing
3131

32+
public export
33+
record KindedName where
34+
constructor MkKindedName
35+
nameKind : Maybe NameType
36+
rawName : Name
37+
38+
export
39+
Show KindedName where show = show . rawName
40+
3241
public export
3342
data Constant
3443
= I Int

src/Idris/Doc/String.idr

Lines changed: 86 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Core.Context
44
import Core.Context.Log
55
import Core.Core
66
import Core.Env
7+
import Core.Metadata
78
import Core.TT
89

910
import Idris.Pretty
@@ -13,6 +14,7 @@ import Idris.Resugar
1314
import Idris.Syntax
1415

1516
import TTImp.TTImp
17+
import TTImp.TTImp.Functor
1618
import TTImp.Elab.Prim
1719

1820
import Data.List
@@ -50,6 +52,7 @@ styleAnn (TCon _) = color BrightBlue
5052
styleAnn DCon = color BrightRed
5153
styleAnn (Fun _) = color BrightGreen
5254
styleAnn Header = underline
55+
styleAnn (Syntax syn) = syntaxAnn syn
5356
styleAnn _ = []
5457

5558
export
@@ -99,17 +102,51 @@ addDocStringNS ns n_in doc
99102
put Syn (record { docstrings $= addName n' doc,
100103
saveDocstrings $= insert n' () } syn)
101104

105+
prettyTerm : IPTerm -> Doc IdrisDocAnn
106+
prettyTerm = reAnnotate Syntax . Idris.Pretty.prettyTerm
107+
108+
showCategory : GlobalDef -> Doc IdrisDocAnn -> Doc IdrisDocAnn
109+
showCategory d = case defDecoration (definition d) of
110+
Nothing => id
111+
Just decor => annotate (Syntax $ SynDecor decor)
112+
113+
prettyName : Name -> Doc IdrisDocAnn
114+
prettyName n =
115+
let root = nameRoot n in
116+
if isOpName n then parens (pretty root) else pretty root
117+
102118
export
103119
getDocsForPrimitive : {auto c : Ref Ctxt Defs} ->
104120
{auto s : Ref Syn SyntaxInfo} ->
105-
Constant -> Core (List String)
121+
Constant -> Core (Doc IdrisDocAnn)
106122
getDocsForPrimitive constant = do
107123
let (_, type) = checkPrim EmptyFC constant
108-
let typeString = show constant ++ " : " ++ show !(resugar [] type)
109-
pure [typeString ++ "\n\tPrimitive"]
110-
111-
prettyTerm : PTerm -> Doc IdrisDocAnn
112-
prettyTerm = reAnnotate Syntax . Idris.Pretty.prettyTerm
124+
let typeString = pretty (show constant)
125+
<++> colon <++> prettyTerm !(resugar [] type)
126+
pure (typeString <+> Line <+> indent 2 "Primitive")
127+
128+
data Config : Type where
129+
||| Configuration of the printer for a name
130+
||| @ longNames Do we print qualified names?
131+
||| @ dropFirst Do we drop the first argument in the type?
132+
||| @ getTotality Do we print the totality status of the function?
133+
MkConfig : {default True longNames : Bool} ->
134+
{default False dropFirst : Bool} ->
135+
{default True getTotality : Bool} ->
136+
Config
137+
138+
||| Printer configuration for interface methods
139+
||| * longNames turned off for interface methods because the namespace is
140+
||| already spelt out for the interface itself
141+
||| * dropFirst turned on for interface methods because the first argument
142+
||| is always the interface constraint
143+
||| * totality turned off for interface methods because the methods themselves
144+
||| are just projections out of a record and so are total
145+
methodsConfig : Config
146+
methodsConfig
147+
= MkConfig {longNames = False}
148+
{dropFirst = True}
149+
{getTotality = False}
113150

114151
export
115152
getDocsForName : {auto o : Ref ROpts REPLOpts} ->
@@ -127,10 +164,12 @@ getDocsForName fc n
127164
| _ => undefinedName fc n
128165
let ns@(_ :: _) = concatMap (\n => lookupName n (docstrings syn)) all
129166
| [] => pure $ pretty ("No documentation for " ++ show n)
130-
docs <- traverse showDoc ns
167+
docs <- traverse (showDoc MkConfig) ns
131168
pure $ vcat (punctuate Line docs)
132169
where
133170

171+
showDoc : Config -> (Name, String) -> Core (Doc IdrisDocAnn)
172+
134173
-- Avoid generating too much whitespace by not returning a single empty line
135174
reflowDoc : String -> List (Doc IdrisDocAnn)
136175
reflowDoc "" = []
@@ -142,11 +181,6 @@ getDocsForName fc n
142181
Unchecked => ""
143182
_ => header "Totality" <++> pretty tot
144183

145-
prettyName : Name -> Doc IdrisDocAnn
146-
prettyName n =
147-
let root = nameRoot n in
148-
if isOpName n then parens (pretty root) else pretty root
149-
150184
getDConDoc : Name -> Core (Doc IdrisDocAnn)
151185
getDConDoc con
152186
= do defs <- get Ctxt
@@ -156,12 +190,13 @@ getDocsForName fc n
156190
syn <- get Syn
157191
ty <- resugar [] =<< normaliseHoles defs [] (type def)
158192
let conWithTypeDoc = annotate (Decl con) (hsep [dCon (prettyName con), colon, prettyTerm ty])
159-
let [(n, str)] = lookupName con (docstrings syn)
160-
| _ => pure conWithTypeDoc
161-
pure $ vcat
162-
[ conWithTypeDoc
163-
, annotate DocStringBody $ vcat $ reflowDoc str
164-
]
193+
case lookupName con (docstrings syn) of
194+
[(n, "")] => pure conWithTypeDoc
195+
[(n, str)] => pure $ vcat
196+
[ conWithTypeDoc
197+
, annotate DocStringBody $ vcat $ reflowDoc str
198+
]
199+
_ => pure conWithTypeDoc
165200

166201
getImplDoc : Name -> Core (List (Doc IdrisDocAnn))
167202
getImplDoc n
@@ -174,16 +209,9 @@ getDocsForName fc n
174209
getMethDoc : Method -> Core (List (Doc IdrisDocAnn))
175210
getMethDoc meth
176211
= do syn <- get Syn
177-
let [(n, str)] = lookupName meth.name (docstrings syn)
212+
let [nstr] = lookupName meth.name (docstrings syn)
178213
| _ => pure []
179-
ty <- pterm meth.type
180-
let nm = prettyName meth.name
181-
pure $ pure $ vcat [
182-
annotate (Decl meth.name) (hsep [fun (meth.name) nm, colon, prettyTerm ty])
183-
, annotate DocStringBody $ vcat (
184-
toList (indent 2 . pretty . show <$> meth.totalReq)
185-
++ reflowDoc str)
186-
]
214+
pure <$> showDoc methodsConfig nstr
187215

188216
getInfixDoc : Name -> Core (List (Doc IdrisDocAnn))
189217
getInfixDoc n
@@ -217,9 +245,12 @@ getDocsForName fc n
217245
[] => []
218246
ps => [hsep (header "Parameters" :: punctuate comma (map (pretty . show) ps))]
219247
let constraints =
220-
case !(traverse pterm (parents iface)) of
248+
case !(traverse (pterm . map (MkKindedName Nothing)) (parents iface)) of
221249
[] => []
222250
ps => [hsep (header "Constraints" :: punctuate comma (map (pretty . show) ps))]
251+
let icon = case dropNS (iconstructor iface) of
252+
DN _ _ => [] -- machine inserted
253+
nm => [hsep [header "Constructor", dCon (prettyName nm)]]
223254
mdocs <- traverse getMethDoc (methods iface)
224255
let meths = case concat mdocs of
225256
[] => []
@@ -233,7 +264,7 @@ getDocsForName fc n
233264
[doc] => [header "Implementation" <++> annotate Declarations doc]
234265
docs => [vcat [header "Implementations"
235266
, annotate Declarations $ vcat $ map (indent 2) docs]]
236-
pure (vcat (params ++ constraints ++ meths ++ insts))
267+
pure (vcat (params ++ constraints ++ icon ++ meths ++ insts))
237268

238269
getFieldDoc : Name -> Core (Doc IdrisDocAnn)
239270
getFieldDoc nm
@@ -243,7 +274,7 @@ getDocsForName fc n
243274
-- should never happen, since we know that the DCon exists:
244275
| Nothing => pure Empty
245276
ty <- resugar [] =<< normaliseHoles defs [] (type def)
246-
let prettyName = pretty (nameRoot nm)
277+
let prettyName = prettyName nm
247278
let projDecl = annotate (Decl nm) $ hsep [ fun nm prettyName, colon, prettyTerm ty ]
248279
case lookupName nm (docstrings syn) of
249280
[(_, "")] => pure projDecl
@@ -290,26 +321,24 @@ getDocsForName fc n
290321
pure (tot ++ cdoc)
291322
_ => pure []
292323

293-
showCategory : GlobalDef -> Doc IdrisDocAnn -> Doc IdrisDocAnn
294-
showCategory d = case definition d of
295-
TCon _ _ _ _ _ _ _ _ => tCon (fullname d)
296-
DCon _ _ _ => dCon
297-
PMDef _ _ _ _ _ => fun (fullname d)
298-
ForeignDef _ _ => fun (fullname d)
299-
Builtin _ => fun (fullname d)
300-
_ => id
301-
302-
showDoc : (Name, String) -> Core (Doc IdrisDocAnn)
303-
showDoc (n, str)
324+
showDoc (MkConfig {longNames, dropFirst, getTotality}) (n, str)
304325
= do defs <- get Ctxt
305326
Just def <- lookupCtxtExact n (gamma defs)
306327
| Nothing => undefinedName fc n
307328
ty <- resugar [] =<< normaliseHoles defs [] (type def)
329+
-- when printing e.g. interface methods there is no point in
330+
-- repeating the interface's name
331+
let ty = ifThenElse (not dropFirst) ty $ case ty of
332+
PPi _ _ AutoImplicit _ _ sc => sc
333+
_ => ty
308334
let cat = showCategory def
309335
nm <- aliasName n
310-
let docDecl = annotate (Decl n) (hsep [cat (pretty (show nm)), colon, prettyTerm ty])
336+
-- when printing e.g. interface methods there is no point in
337+
-- repeating the namespace the interface lives in
338+
let nm = if longNames then pretty (show nm) else prettyName nm
339+
let docDecl = annotate (Decl n) (hsep [cat nm, colon, prettyTerm ty])
311340
let docText = reflowDoc str
312-
extra <- getExtra n def
341+
extra <- ifThenElse getTotality (getExtra n def) (pure [])
313342
fixes <- getFixityDoc n
314343
let docBody = annotate DocStringBody $ vcat $ docText ++ (map (indent 2) (extra ++ fixes))
315344
pure (vcat [docDecl, docBody])
@@ -320,7 +349,8 @@ getDocsForPTerm : {auto o : Ref ROpts REPLOpts} ->
320349
{auto s : Ref Syn SyntaxInfo} ->
321350
PTerm -> Core (List String)
322351
getDocsForPTerm (PRef fc name) = pure $ [!(render styleAnn !(getDocsForName fc name))]
323-
getDocsForPTerm (PPrimVal _ constant) = getDocsForPrimitive constant
352+
getDocsForPTerm (PPrimVal _ constant)
353+
= pure [!(render styleAnn !(getDocsForPrimitive constant))]
324354
getDocsForPTerm (PType _) = pure ["Type : Type\n\tThe type of all types is Type. The type of Type is Type."]
325355
getDocsForPTerm (PString _ _) = pure ["String Literal\n\tDesugars to a fromString call"]
326356
getDocsForPTerm (PList _ _ _) = pure ["List Literal\n\tDesugars to (::) and Nil"]
@@ -332,24 +362,26 @@ getDocsForPTerm pterm = pure ["Docs not implemented for " ++ show pterm ++ " yet
332362

333363
summarise : {auto c : Ref Ctxt Defs} ->
334364
{auto s : Ref Syn SyntaxInfo} ->
335-
Name -> Core String
365+
Name -> Core (Doc IdrisDocAnn)
336366
summarise n -- n is fully qualified
337367
= do syn <- get Syn
338368
defs <- get Ctxt
339369
Just def <- lookupCtxtExact n (gamma defs)
340370
| _ => pure ""
341-
let doc = case lookupName n (docstrings syn) of
342-
[(_, doc)] => case Extra.lines doc of
343-
("" ::: _) => Nothing
344-
(d ::: _) => Just d
345-
_ => Nothing
371+
-- let doc = case lookupName n (docstrings syn) of
372+
-- [(_, doc)] => case Extra.lines doc of
373+
-- ("" ::: _) => Nothing
374+
-- (d ::: _) => Just d
375+
-- _ => Nothing
346376
ty <- normaliseHoles defs [] (type def)
347-
pure (nameRoot n ++ " : " ++ show !(resugar [] ty) ++
348-
maybe "" ((++) "\n\t") doc)
377+
pure $ showCategory def (prettyName n)
378+
<++> colon <++> hang 0 (prettyTerm !(resugar [] ty))
379+
-- <+> maybe "" ((Line <+>) . indent 2 . pretty) doc)
349380

350381
-- Display all the exported names in the given namespace
351382
export
352-
getContents : {auto c : Ref Ctxt Defs} ->
383+
getContents : {auto o : Ref ROpts REPLOpts} ->
384+
{auto c : Ref Ctxt Defs} ->
353385
{auto s : Ref Syn SyntaxInfo} ->
354386
Namespace -> Core (List String)
355387
getContents ns
@@ -359,7 +391,7 @@ getContents ns
359391
ns <- allNames (gamma defs)
360392
let allNs = filter inNS ns
361393
allNs <- filterM (visible defs) allNs
362-
traverse summarise (sort allNs)
394+
traverse (\ ns => render styleAnn !(summarise ns)) (sort allNs)
363395
where
364396
visible : Defs -> Name -> Core Bool
365397
visible defs n

src/Idris/Elab/Implementation.idr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import TTImp.Elab
1717
import TTImp.Elab.Check
1818
import TTImp.ProcessDecls
1919
import TTImp.TTImp
20+
import TTImp.TTImp.Functor
2021
import TTImp.Unelab
2122
import TTImp.Utils
2223

@@ -101,7 +102,7 @@ getMethImps : {vars : _} ->
101102
Env Term vars -> Term vars ->
102103
Core (List (Name, RigCount, RawImp))
103104
getMethImps env (Bind fc x (Pi fc' c Implicit ty) sc)
104-
= do rty <- unelabNoSugar env ty
105+
= do rty <- map (map rawName) $ unelabNoSugar env ty
105106
ts <- getMethImps (Pi fc' c Implicit ty :: env) sc
106107
pure ((x, c, rty) :: ts)
107108
getMethImps env tm = pure []

src/Idris/Error.idr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Core.CaseTree
44
import Core.Core
55
import Core.Context
66
import Core.Env
7+
import Core.Metadata
78
import Core.Options
89
import Core.Value
910

@@ -38,7 +39,7 @@ import System.File
3839
%default covering
3940

4041
keyword : Doc IdrisAnn -> Doc IdrisAnn
41-
keyword = annotate (Syntax SynKeyword)
42+
keyword = annotate (Syntax $ SynDecor Keyword)
4243

4344
-- | Add binding site information if the term is simply a machine-inserted name
4445
pShowMN : {vars : _} -> Term vars -> Env t vars -> Doc IdrisAnn -> Doc IdrisAnn

src/Idris/IDEMode/CaseSplit.idr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Parser.Unlit
1212

1313
import TTImp.Interactive.CaseSplit
1414
import TTImp.TTImp
15+
import TTImp.TTImp.Functor
1516
import TTImp.Utils
1617

1718
import Idris.IDEMode.TokenLine
@@ -44,10 +45,10 @@ toStrUpdate : {auto c : Ref Ctxt Defs} ->
4445
{auto s : Ref Syn SyntaxInfo} ->
4546
(Name, RawImp) -> Core Updates
4647
toStrUpdate (UN n, term)
47-
= do clause <- pterm term
48+
= do clause <- pterm (map (MkKindedName Nothing) term) -- hack
4849
pure [(n, show (bracket clause))]
4950
where
50-
bracket : PTerm -> PTerm
51+
bracket : PTerm' nm -> PTerm' nm
5152
bracket tm@(PRef _ _) = tm
5253
bracket tm@(PList _ _ _) = tm
5354
bracket tm@(PSnocList _ _ _) = tm
@@ -146,7 +147,7 @@ showImpossible : {auto c : Ref Ctxt Defs} ->
146147
{auto o : Ref ROpts REPLOpts} ->
147148
(indent : Nat) -> RawImp -> Core String
148149
showImpossible indent lhs
149-
= do clause <- pterm lhs
150+
= do clause <- pterm (map (MkKindedName Nothing) lhs) -- hack
150151
pure (fastPack (replicate indent ' ') ++ show clause ++ " impossible")
151152

152153
-- Given a list of updates and a line and column, find the relevant line in

src/Idris/IDEMode/Holes.idr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public export
1818
record HolePremise where
1919
constructor MkHolePremise
2020
name : Name
21-
type : PTerm
21+
type : IPTerm
2222
multiplicity : RigCount
2323
isImplicit : Bool
2424

@@ -27,7 +27,7 @@ public export
2727
record HoleData where
2828
constructor MkHoleData
2929
name : Name
30-
type : PTerm
30+
type : IPTerm
3131
context : List HolePremise
3232

3333
||| If input is a hole, return number of locals in scope at binding

0 commit comments

Comments
 (0)