correctly lex quotations and antiquotations and do completion inside antiquotations
Ignore-this: 399f6b2dd65fd530e684d09cf5d57d0a darcs-hash:20120222155931-c41ad-835a2ccf63ac1e853846972880a49d1f8ff6a236
This commit is contained in:
parent
394175914d
commit
4fc06ba0a3
|
@ -65,7 +65,6 @@ let parse_toplevel_phrase str eos_is_error =
|
||||||
UTop.Error (locs, msg)
|
UTop.Error (locs, msg)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
UTop.set_camlp4 true;
|
|
||||||
UTop.parse_toplevel_phrase := parse_toplevel_phrase;
|
UTop.parse_toplevel_phrase := parse_toplevel_phrase;
|
||||||
(* Force camlp4 to display its welcome message. *)
|
(* Force camlp4 to display its welcome message. *)
|
||||||
try
|
try
|
||||||
|
|
|
@ -59,7 +59,12 @@ let make_variable ?eq x =
|
||||||
let signal, set = S.create ?eq x in
|
let signal, set = S.create ?eq x in
|
||||||
(signal, (fun () -> S.value signal), set)
|
(signal, (fun () -> S.value signal), set)
|
||||||
|
|
||||||
let camlp4, get_camlp4, set_camlp4 = make_variable true
|
type syntax =
|
||||||
|
| Normal
|
||||||
|
| Camlp4o
|
||||||
|
| Camlp4r
|
||||||
|
|
||||||
|
let syntax, get_syntax, set_syntax = make_variable Normal
|
||||||
let phrase_terminator, get_phrase_terminator, set_phrase_terminator = make_variable ";;"
|
let phrase_terminator, get_phrase_terminator, set_phrase_terminator = make_variable ";;"
|
||||||
let auto_run_lwt, get_auto_run_lwt, set_auto_run_lwt = make_variable true
|
let auto_run_lwt, get_auto_run_lwt, set_auto_run_lwt = make_variable true
|
||||||
|
|
||||||
|
@ -455,6 +460,7 @@ let () =
|
||||||
"camlp4o"
|
"camlp4o"
|
||||||
(Toploop.Directive_none
|
(Toploop.Directive_none
|
||||||
(fun () ->
|
(fun () ->
|
||||||
|
set_syntax Camlp4o;
|
||||||
set_phrase_terminator ";;";
|
set_phrase_terminator ";;";
|
||||||
try
|
try
|
||||||
Topfind.syntax "camlp4o";
|
Topfind.syntax "camlp4o";
|
||||||
|
@ -467,6 +473,7 @@ let () =
|
||||||
"camlp4r"
|
"camlp4r"
|
||||||
(Toploop.Directive_none
|
(Toploop.Directive_none
|
||||||
(fun () ->
|
(fun () ->
|
||||||
|
set_syntax Camlp4r;
|
||||||
set_phrase_terminator ";";
|
set_phrase_terminator ";";
|
||||||
try
|
try
|
||||||
Topfind.syntax "camlp4r";
|
Topfind.syntax "camlp4r";
|
||||||
|
|
|
@ -29,16 +29,25 @@ type ui = Console | Emacs
|
||||||
val get_ui : unit -> ui
|
val get_ui : unit -> ui
|
||||||
(** Returns the user interface in use. *)
|
(** Returns the user interface in use. *)
|
||||||
|
|
||||||
val camlp4 : bool signal
|
(** Syntax. *)
|
||||||
(** [true] if the lexer should recognize camlp4 quotations. This
|
type syntax =
|
||||||
variable is automatically set to [true] when you type [#camlp4o]
|
| Normal
|
||||||
or [#camlp4r]. *)
|
(** No camlp4. *)
|
||||||
|
| Camlp4o
|
||||||
|
(** Camlp4, original syntax. *)
|
||||||
|
| Camlp4r
|
||||||
|
(** Camlp4, revised syntax. *)
|
||||||
|
|
||||||
val get_camlp4 : unit -> bool
|
val syntax : syntax signal
|
||||||
(** Returns the current value of {!camlp4}. *)
|
(** The syntax in use. If it is {!Camlp4o} or {!Camlp4r} quotations
|
||||||
|
are recognized. It is modified when you type [#camlp4o] or
|
||||||
|
[#camlp4r]. *)
|
||||||
|
|
||||||
val set_camlp4 : bool -> unit
|
val get_syntax : unit -> syntax
|
||||||
(** Modifies {!camlp4}. *)
|
(** Returns the current value of {!syntax}. *)
|
||||||
|
|
||||||
|
val set_syntax : syntax -> unit
|
||||||
|
(** Modifies {!syntax}. *)
|
||||||
|
|
||||||
val phrase_terminator : string signal
|
val phrase_terminator : string signal
|
||||||
(** The phrase terminator. It is ";;" by default and ";" when you
|
(** The phrase terminator. It is ";;" by default and ";" when you
|
||||||
|
|
|
@ -60,9 +60,9 @@ type value_or_field = Value | Field
|
||||||
let parse_longident tokens =
|
let parse_longident tokens =
|
||||||
let rec loop acc tokens =
|
let rec loop acc tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Symbol, _, _, ".") :: (Uident, _, _, id) :: tokens ->
|
| (Symbol ".", _) :: (Uident id, _) :: tokens ->
|
||||||
loop (id :: acc) tokens
|
loop (id :: acc) tokens
|
||||||
| (Symbol, _, _, ".") :: (Lident, _, _, id) :: tokens ->
|
| (Symbol ".", _) :: (Lident id, _) :: tokens ->
|
||||||
(Field,
|
(Field,
|
||||||
match acc with
|
match acc with
|
||||||
| [] -> None
|
| [] -> None
|
||||||
|
@ -74,18 +74,18 @@ let parse_longident tokens =
|
||||||
| l -> Some (longident_of_list l))
|
| l -> Some (longident_of_list l))
|
||||||
in
|
in
|
||||||
match tokens with
|
match tokens with
|
||||||
| ((Comment false | Doc false | String false | Quotation false), _, _, _) :: _ ->
|
| ((Comment (_, false) | String false | Quotation (_, false)), _) :: _ ->
|
||||||
(* An unterminated command, string, or quotation. *)
|
(* An unterminated command, string, or quotation. *)
|
||||||
None
|
None
|
||||||
| ((Uident | Lident), start, _, id) :: tokens ->
|
| ((Uident id | Lident id), { idx1 = start }) :: tokens ->
|
||||||
(* An identifier. *)
|
(* An identifier. *)
|
||||||
let kind, path = loop [] tokens in
|
let kind, path = loop [] tokens in
|
||||||
Some (kind, path, start, id)
|
Some (kind, path, start, id)
|
||||||
| (Blanks, _, stop, _) :: tokens ->
|
| (Blanks, { idx2 = stop }) :: tokens ->
|
||||||
(* Some blanks at the end. *)
|
(* Some blanks at the end. *)
|
||||||
let kind, path = loop [] tokens in
|
let kind, path = loop [] tokens in
|
||||||
Some (kind, path, stop, "")
|
Some (kind, path, stop, "")
|
||||||
| (_, _, stop, _) :: _ ->
|
| (_, { idx2 = stop }) :: _ ->
|
||||||
(* Otherwise complete after the last token. *)
|
(* Otherwise complete after the last token. *)
|
||||||
let kind, path = loop [] tokens in
|
let kind, path = loop [] tokens in
|
||||||
Some (kind, path, stop, "")
|
Some (kind, path, stop, "")
|
||||||
|
@ -98,7 +98,7 @@ let parse_method tokens =
|
||||||
longidentifier. *)
|
longidentifier. *)
|
||||||
let rec loop_uidents acc tokens =
|
let rec loop_uidents acc tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Symbol, _, _, ".") :: (Uident, _, _, id) :: tokens ->
|
| (Symbol ".", _) :: (Uident id, _) :: tokens ->
|
||||||
loop_uidents (id :: acc) tokens
|
loop_uidents (id :: acc) tokens
|
||||||
| _ ->
|
| _ ->
|
||||||
longident_of_list acc
|
longident_of_list acc
|
||||||
|
@ -106,21 +106,21 @@ let parse_method tokens =
|
||||||
(* Collect [m1#m2# ... #mp] *)
|
(* Collect [m1#m2# ... #mp] *)
|
||||||
let rec loop_methods acc tokens =
|
let rec loop_methods acc tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Lident, _, _, meth) :: (Symbol, _, _, "#") :: tokens ->
|
| (Lident meth, _) :: (Symbol "#", _) :: tokens ->
|
||||||
loop_methods (meth :: acc) tokens
|
loop_methods (meth :: acc) tokens
|
||||||
| (Lident, _, _, id) :: tokens ->
|
| (Lident id, _) :: tokens ->
|
||||||
Some (loop_uidents [id] tokens, acc)
|
Some (loop_uidents [id] tokens, acc)
|
||||||
| _ ->
|
| _ ->
|
||||||
None
|
None
|
||||||
in
|
in
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Lident, start, _, meth) :: (Symbol, _, _, "#") :: tokens -> begin
|
| (Lident meth, { idx1 = start }) :: (Symbol "#", _) :: tokens -> begin
|
||||||
match loop_methods [] tokens with
|
match loop_methods [] tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (path, meths) -> Some (path, meths, start, meth)
|
| Some (path, meths) -> Some (path, meths, start, meth)
|
||||||
end
|
end
|
||||||
| (Symbol, _, stop, "#") :: tokens
|
| (Symbol "#", { idx2 = stop }) :: tokens
|
||||||
| (Blanks, _, stop, _) :: (Symbol, _, _, "#") :: tokens -> begin
|
| (Blanks, { idx2 = stop }) :: (Symbol "#", _) :: tokens -> begin
|
||||||
match loop_methods [] tokens with
|
match loop_methods [] tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (path, meths) -> Some (path, meths, stop, "")
|
| Some (path, meths) -> Some (path, meths, stop, "")
|
||||||
|
@ -140,21 +140,21 @@ let parse_label tokens =
|
||||||
(* Collect [M1.M2. ... .Mn] *)
|
(* Collect [M1.M2. ... .Mn] *)
|
||||||
let rec loop_uidents acc_uidents acc_methods tokens =
|
let rec loop_uidents acc_uidents acc_methods tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Lident, _, _, "new") :: _ ->
|
| (Lident "new", _) :: _ ->
|
||||||
Some (New, longident_of_list acc_uidents, acc_methods)
|
Some (New, longident_of_list acc_uidents, acc_methods)
|
||||||
| ((Lident | Uident), _, _, id) :: _ when String_set.mem id !UTop.keywords ->
|
| ((Lident id | Uident id), _) :: _ when String_set.mem id !UTop.keywords ->
|
||||||
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
||||||
| (Symbol, _, _, ".") :: (Uident, _, _, id) :: tokens ->
|
| (Symbol ".", _) :: (Uident id, _) :: tokens ->
|
||||||
loop_uidents (id :: acc_uidents) acc_methods tokens
|
loop_uidents (id :: acc_uidents) acc_methods tokens
|
||||||
| (Symbol, _, _, ("~" | "?" | ":" | "." | "#" | "!" | "`")) :: tokens ->
|
| (Symbol ("~" | "?" | ":" | "." | "#" | "!" | "`"), _) :: tokens ->
|
||||||
search tokens
|
search tokens
|
||||||
| (Symbol, _, _, ")") :: tokens ->
|
| (Symbol ")", _) :: tokens ->
|
||||||
skip tokens "(" []
|
skip tokens "(" []
|
||||||
| (Symbol, _, _, "}") :: tokens ->
|
| (Symbol "}", _) :: tokens ->
|
||||||
skip tokens "{" []
|
skip tokens "{" []
|
||||||
| (Symbol, _, _, "]") :: tokens ->
|
| (Symbol "]", _) :: tokens ->
|
||||||
skip tokens "[" []
|
skip tokens "[" []
|
||||||
| (Symbol, _, _, _) :: _ ->
|
| (Symbol _, _) :: _ ->
|
||||||
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
||||||
| [] ->
|
| [] ->
|
||||||
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
Some (Fun, longident_of_list acc_uidents, acc_methods)
|
||||||
|
@ -162,21 +162,21 @@ let parse_label tokens =
|
||||||
search tokens
|
search tokens
|
||||||
and loop_methods acc tokens =
|
and loop_methods acc tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| ((Lident | Uident), _, _, id) :: _ when String_set.mem id !UTop.keywords ->
|
| ((Lident id | Uident id), _) :: _ when String_set.mem id !UTop.keywords ->
|
||||||
None
|
None
|
||||||
| (Symbol, _, _, ("~" | "?" | ":" | "." | "#" | "!" | "`")) :: tokens ->
|
| (Symbol ("~" | "?" | ":" | "." | "#" | "!" | "`"), _) :: tokens ->
|
||||||
search tokens
|
search tokens
|
||||||
| (Symbol, _, _, ")") :: tokens ->
|
| (Symbol ")", _) :: tokens ->
|
||||||
skip tokens "(" []
|
skip tokens "(" []
|
||||||
| (Symbol, _, _, "}") :: tokens ->
|
| (Symbol "}", _) :: tokens ->
|
||||||
skip tokens "{" []
|
skip tokens "{" []
|
||||||
| (Symbol, _, _, "]") :: tokens ->
|
| (Symbol "]", _) :: tokens ->
|
||||||
skip tokens "[" []
|
skip tokens "[" []
|
||||||
| (Symbol, _, _, _) :: _ ->
|
| (Symbol _, _) :: _ ->
|
||||||
None
|
None
|
||||||
| (Lident, _, _, id) :: (Symbol, _, _, "#") :: tokens ->
|
| (Lident id, _) :: (Symbol "#", _) :: tokens ->
|
||||||
loop_methods (id :: acc) tokens
|
loop_methods (id :: acc) tokens
|
||||||
| (Lident, _, _, id) :: tokens ->
|
| (Lident id, _) :: tokens ->
|
||||||
loop_uidents [id] acc tokens
|
loop_uidents [id] acc tokens
|
||||||
| [] ->
|
| [] ->
|
||||||
None
|
None
|
||||||
|
@ -184,21 +184,21 @@ let parse_label tokens =
|
||||||
search tokens
|
search tokens
|
||||||
and search tokens =
|
and search tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| ((Lident | Uident), _, _, id) :: _ when String_set.mem id !UTop.keywords ->
|
| ((Lident id | Uident id), _) :: _ when String_set.mem id !UTop.keywords ->
|
||||||
None
|
None
|
||||||
| (Symbol, _, _, ("~" | "?" | ":" | "." | "#" | "!" | "`")) :: tokens ->
|
| (Symbol ("~" | "?" | ":" | "." | "#" | "!" | "`"), _) :: tokens ->
|
||||||
search tokens
|
search tokens
|
||||||
| (Symbol, _, _, ")") :: tokens ->
|
| (Symbol ")", _) :: tokens ->
|
||||||
skip tokens "(" []
|
skip tokens "(" []
|
||||||
| (Symbol, _, _, "}") :: tokens ->
|
| (Symbol "}", _) :: tokens ->
|
||||||
skip tokens "{" []
|
skip tokens "{" []
|
||||||
| (Symbol, _, _, "]") :: tokens ->
|
| (Symbol "]", _) :: tokens ->
|
||||||
skip tokens "[" []
|
skip tokens "[" []
|
||||||
| (Symbol, _, _, _) :: _ ->
|
| (Symbol _, _) :: _ ->
|
||||||
None
|
None
|
||||||
| (Lident, _, _, id) :: (Symbol, _, _, "#") :: tokens ->
|
| (Lident id, _) :: (Symbol "#", _) :: tokens ->
|
||||||
loop_methods [id] tokens
|
loop_methods [id] tokens
|
||||||
| (Lident, _, _, id) :: tokens ->
|
| (Lident id, _) :: tokens ->
|
||||||
loop_uidents [id] [] tokens
|
loop_uidents [id] [] tokens
|
||||||
| _ :: tokens ->
|
| _ :: tokens ->
|
||||||
search tokens
|
search tokens
|
||||||
|
@ -206,16 +206,16 @@ let parse_label tokens =
|
||||||
None
|
None
|
||||||
and skip tokens top stack =
|
and skip tokens top stack =
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Symbol, _, _, symbol) :: tokens when symbol = top -> begin
|
| (Symbol symbol, _) :: tokens when symbol = top -> begin
|
||||||
match stack with
|
match stack with
|
||||||
| [] -> search tokens
|
| [] -> search tokens
|
||||||
| top :: stack -> skip tokens top stack
|
| top :: stack -> skip tokens top stack
|
||||||
end
|
end
|
||||||
| (Symbol, _, _, ")") :: tokens ->
|
| (Symbol ")", _) :: tokens ->
|
||||||
skip tokens "(" (top :: stack)
|
skip tokens "(" (top :: stack)
|
||||||
| (Symbol, _, _, "}") :: tokens ->
|
| (Symbol "}", _) :: tokens ->
|
||||||
skip tokens "{" (top :: stack)
|
skip tokens "{" (top :: stack)
|
||||||
| (Symbol, _, _, "]") :: tokens ->
|
| (Symbol "]", _) :: tokens ->
|
||||||
skip tokens "[" (top :: stack)
|
skip tokens "[" (top :: stack)
|
||||||
| _ :: tokens ->
|
| _ :: tokens ->
|
||||||
skip tokens top stack
|
skip tokens top stack
|
||||||
|
@ -223,22 +223,22 @@ let parse_label tokens =
|
||||||
None
|
None
|
||||||
in
|
in
|
||||||
match tokens with
|
match tokens with
|
||||||
| (Lident, start, _, label) :: (Symbol, _, _, "~") :: tokens -> begin
|
| (Lident label, { idx1 = start }) :: (Symbol "~", _) :: tokens -> begin
|
||||||
match search tokens with
|
match search tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (kind, id, meths) -> Some (kind, id, meths, Required, start, label)
|
| Some (kind, id, meths) -> Some (kind, id, meths, Required, start, label)
|
||||||
end
|
end
|
||||||
| (Symbol, _, stop, "~") :: tokens -> begin
|
| (Symbol "~", { idx2 = stop }) :: tokens -> begin
|
||||||
match search tokens with
|
match search tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (kind, id, meths) -> Some (kind, id, meths, Required, stop, "")
|
| Some (kind, id, meths) -> Some (kind, id, meths, Required, stop, "")
|
||||||
end
|
end
|
||||||
| (Lident, start, _, label) :: (Symbol, _, _, "?") :: tokens -> begin
|
| (Lident label, { idx1 = start }) :: (Symbol "?", _) :: tokens -> begin
|
||||||
match search tokens with
|
match search tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (kind, id, meths) -> Some (kind, id, meths, Optional, start, label)
|
| Some (kind, id, meths) -> Some (kind, id, meths, Optional, start, label)
|
||||||
end
|
end
|
||||||
| (Symbol, _, stop, "?") :: tokens -> begin
|
| (Symbol "?", { idx2 = stop }) :: tokens -> begin
|
||||||
match search tokens with
|
match search tokens with
|
||||||
| None -> None
|
| None -> None
|
||||||
| Some (kind, id, meths) -> Some (kind, id, meths, Optional, stop, "")
|
| Some (kind, id, meths) -> Some (kind, id, meths, Optional, stop, "")
|
||||||
|
@ -250,13 +250,13 @@ let parse_label tokens =
|
||||||
| Directive listing |
|
| Directive listing |
|
||||||
+-----------------------------------------------------------------+ *)
|
+-----------------------------------------------------------------+ *)
|
||||||
|
|
||||||
let list_directives () =
|
let list_directives phrase_terminator =
|
||||||
String_map.bindings
|
String_map.bindings
|
||||||
(Hashtbl.fold
|
(Hashtbl.fold
|
||||||
(fun dir kind map ->
|
(fun dir kind map ->
|
||||||
let suffix =
|
let suffix =
|
||||||
match kind with
|
match kind with
|
||||||
| Toploop.Directive_none _ -> ";;"
|
| Toploop.Directive_none _ -> phrase_terminator
|
||||||
| Toploop.Directive_string _ -> " \""
|
| Toploop.Directive_string _ -> " \""
|
||||||
| Toploop.Directive_bool _ | Toploop.Directive_int _ | Toploop.Directive_ident _ -> " "
|
| Toploop.Directive_bool _ | Toploop.Directive_int _ | Toploop.Directive_ident _ -> " "
|
||||||
in
|
in
|
||||||
|
@ -634,50 +634,79 @@ let labels_of_newclass longident =
|
||||||
labels_of_type String_map.empty type_expr
|
labels_of_type String_map.empty type_expr
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
(* +-----------------------------------------------------------------+
|
||||||
| Filtering |
|
| Tokens processing |
|
||||||
+-----------------------------------------------------------------+ *)
|
+-----------------------------------------------------------------+ *)
|
||||||
|
|
||||||
(* Filter blanks and comments except for the last token. *)
|
(* Filter blanks and comments except for the last token. *)
|
||||||
let rec filter tokens =
|
let rec filter tokens =
|
||||||
match tokens with
|
match tokens with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| [((Blanks | Comment true | Doc true), start, stop, src)] -> [(Blanks, start, stop, src)]
|
| [((Blanks | Comment (_, true)), loc)] -> [(Blanks, loc)]
|
||||||
| ((Blanks | Comment true | Doc true), _, _, _) :: rest -> filter rest
|
| ((Blanks | Comment (_, true)), _) :: rest -> filter rest
|
||||||
| x :: rest -> x :: filter rest
|
| x :: rest -> x :: filter rest
|
||||||
|
|
||||||
|
(* Reverse and filter blanks and comments except for the last
|
||||||
|
token. *)
|
||||||
|
let rec rev_filter acc tokens =
|
||||||
|
match tokens with
|
||||||
|
| [] -> acc
|
||||||
|
| [((Blanks | Comment (_, true)), loc)] -> (Blanks, loc) :: acc
|
||||||
|
| ((Blanks | Comment (_, true)), _) :: rest -> rev_filter acc rest
|
||||||
|
| x :: rest -> rev_filter (x :: acc) rest
|
||||||
|
|
||||||
|
(* Find the current context. *)
|
||||||
|
let rec find_context tokens = function
|
||||||
|
| [] ->
|
||||||
|
Some (rev_filter [] tokens)
|
||||||
|
| [(Quotation (items, false), _)] ->
|
||||||
|
find_context_in_quotation items
|
||||||
|
| _ :: rest ->
|
||||||
|
find_context tokens rest
|
||||||
|
|
||||||
|
and find_context_in_quotation = function
|
||||||
|
| [] ->
|
||||||
|
None
|
||||||
|
| [(Quot_anti { a_closing = None; a_contents = tokens }, _)] ->
|
||||||
|
find_context tokens tokens
|
||||||
|
| _ :: rest ->
|
||||||
|
find_context_in_quotation rest
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
(* +-----------------------------------------------------------------+
|
||||||
| Completion |
|
| Completion |
|
||||||
+-----------------------------------------------------------------+ *)
|
+-----------------------------------------------------------------+ *)
|
||||||
|
|
||||||
let complete str =
|
let complete ~syntax ~phrase_terminator ~input =
|
||||||
let tokens = UTop_lexer.lex_string ~camlp4:(UTop.get_camlp4 ()) str in
|
let tokens = UTop_lexer.lex_string syntax input in
|
||||||
(* Filter blanks and comments. *)
|
(* Filter blanks and comments. *)
|
||||||
let tokens = filter tokens in
|
let tokens = filter tokens in
|
||||||
match tokens with
|
match tokens with
|
||||||
|
|
||||||
(* Completion on directive names. *)
|
(* Completion on directive names. *)
|
||||||
| [(Symbol, _, stop, "#")]
|
| [(Symbol "#", { idx2 = stop })]
|
||||||
| [(Symbol, _, _, "#"); (Blanks, _, stop, _)] ->
|
| [(Symbol "#", _); (Blanks, { idx2 = stop })] ->
|
||||||
(stop, list_directives ())
|
(stop, list_directives phrase_terminator)
|
||||||
| [(Symbol, _, _, "#"); ((Lident | Uident), start, _, src)] ->
|
| [(Symbol "#", _); ((Lident src | Uident src), { idx1 = start })] ->
|
||||||
(start, lookup_assoc src (list_directives ()))
|
(start, lookup_assoc src (list_directives phrase_terminator))
|
||||||
|
|
||||||
(* Complete with ";;" when possible. *)
|
(* Complete with ";;" when possible. *)
|
||||||
| [(Symbol, _, _, "#"); ((Lident | Uident), _, _, _); (String true, _, stop, _)]
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, { idx2 = stop })]
|
||||||
| [(Symbol, _, _, "#"); ((Lident | Uident), _, _, _); (String true, _, _, _); (Blanks, _, stop, _)] ->
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, _); (Blanks, { idx2 = stop })] ->
|
||||||
(stop, [(";;", "")])
|
(stop, [(phrase_terminator, "")])
|
||||||
| [(Symbol, _, _, "#"); ((Lident | Uident), _, _, _); (String true, _, _, _); (Symbol, start, _, ";")] ->
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, _); (Symbol sym, { idx1 = start })] ->
|
||||||
(start, [(";;", "")])
|
if Zed_utf8.starts_with phrase_terminator sym then
|
||||||
|
(start, [(phrase_terminator, "")])
|
||||||
|
else
|
||||||
|
(0, [])
|
||||||
|
|
||||||
(* Completion on #require. *)
|
(* Completion on #require. *)
|
||||||
| [(Symbol, _, _, "#"); (Lident, _, _, "require"); (String false, start, stop, str)] ->
|
| [(Symbol "#", _); (Lident "require", _); (String false, loc)] ->
|
||||||
let pkg = String.sub str 1 (String.length str - 1) in
|
let pkg = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||||
let pkgs = lookup pkg (Fl_package_base.list_packages ()) in
|
let pkgs = lookup pkg (Fl_package_base.list_packages ()) in
|
||||||
(start + 1, List.map (fun pkg -> (pkg, "\";;")) (List.sort compare pkgs))
|
(loc.idx1 + 1, List.map (fun pkg -> (pkg, "\"" ^ phrase_terminator)) (List.sort compare pkgs))
|
||||||
|
|
||||||
(* Completion on #load. *)
|
(* Completion on #load. *)
|
||||||
| [(Symbol, _, _, "#"); (Lident, _, _, "load"); (String false, start, stop, str)] ->
|
| [(Symbol "#", _); (Lident "load", _); (String false, loc)] ->
|
||||||
let file = String.sub str 1 (String.length str - 1) in
|
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||||
let filter name = Filename.check_suffix name ".cma" || Filename.check_suffix name ".cmo" in
|
let filter name = Filename.check_suffix name ".cma" || Filename.check_suffix name ".cmo" in
|
||||||
let map =
|
let map =
|
||||||
if Filename.is_relative file then
|
if Filename.is_relative file then
|
||||||
|
@ -692,12 +721,12 @@ let complete str =
|
||||||
let list = String_map.bindings map in
|
let list = String_map.bindings map in
|
||||||
let name = basename file in
|
let name = basename file in
|
||||||
let result = lookup_assoc name list in
|
let result = lookup_assoc name list in
|
||||||
(stop - Zed_utf8.length name,
|
(loc.idx2 - Zed_utf8.length name,
|
||||||
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\";;")) result)
|
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\"" ^ phrase_terminator)) result)
|
||||||
|
|
||||||
(* Completion on #use. *)
|
(* Completion on #use. *)
|
||||||
| [(Symbol, _, _, "#"); (Lident, _, _, "use"); (String false, start, stop, str)] ->
|
| [(Symbol "#", _); (Lident "use", _); (String false, loc)] ->
|
||||||
let file = String.sub str 1 (String.length str - 1) in
|
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||||
let filter name =
|
let filter name =
|
||||||
match try Some (String.rindex name '.') with Not_found -> None with
|
match try Some (String.rindex name '.') with Not_found -> None with
|
||||||
| None ->
|
| None ->
|
||||||
|
@ -719,28 +748,28 @@ let complete str =
|
||||||
let list = String_map.bindings map in
|
let list = String_map.bindings map in
|
||||||
let name = basename file in
|
let name = basename file in
|
||||||
let result = lookup_assoc name list in
|
let result = lookup_assoc name list in
|
||||||
(stop - Zed_utf8.length name,
|
(loc.idx2 - Zed_utf8.length name,
|
||||||
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\";;")) result)
|
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\"" ^ phrase_terminator)) result)
|
||||||
|
|
||||||
(* Completion on #directory and #cd. *)
|
(* Completion on #directory and #cd. *)
|
||||||
| [(Symbol, _, _, "#"); (Lident, _, _, ("cd" | "directory")); (String false, start, stop, str)] ->
|
| [(Symbol "#", _); (Lident ("cd" | "directory"), _); (String false, loc)] ->
|
||||||
let file = String.sub str 1 (String.length str - 1) in
|
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||||
let list = list_directories (Filename.dirname file) in
|
let list = list_directories (Filename.dirname file) in
|
||||||
let name = basename file in
|
let name = basename file in
|
||||||
let result = lookup name list in
|
let result = lookup name list in
|
||||||
(stop - Zed_utf8.length name, List.map (function dir -> (dir, "")) result)
|
(loc.idx2 - Zed_utf8.length name, List.map (function dir -> (dir, "")) result)
|
||||||
|
|
||||||
(* Generic completion on directives. *)
|
(* Generic completion on directives. *)
|
||||||
| [(Symbol, _, _, "#"); ((Lident | Uident), _, _, dir); (Blanks, _, stop, _)] ->
|
| [(Symbol "#", _); ((Lident dir | Uident dir), _); (Blanks, { idx2 = stop })] ->
|
||||||
(stop,
|
(stop,
|
||||||
match try Some (Hashtbl.find Toploop.directive_table dir) with Not_found -> None with
|
match try Some (Hashtbl.find Toploop.directive_table dir) with Not_found -> None with
|
||||||
| Some (Toploop.Directive_none _) -> [(";;", "")]
|
| Some (Toploop.Directive_none _) -> [(phrase_terminator, "")]
|
||||||
| Some (Toploop.Directive_string _) -> [(" \"", "")]
|
| Some (Toploop.Directive_string _) -> [(" \"", "")]
|
||||||
| Some (Toploop.Directive_bool _) -> [("true", ";;"); ("false", ";;")]
|
| Some (Toploop.Directive_bool _) -> [("true", phrase_terminator); ("false", phrase_terminator)]
|
||||||
| Some (Toploop.Directive_int _) -> []
|
| Some (Toploop.Directive_int _) -> []
|
||||||
| Some (Toploop.Directive_ident _) -> List.map (fun w -> (w, "")) (String_set.elements (Lazy.force !global_names))
|
| Some (Toploop.Directive_ident _) -> List.map (fun w -> (w, "")) (String_set.elements (Lazy.force !global_names))
|
||||||
| None -> [])
|
| None -> [])
|
||||||
| (Symbol, _, _, "#") :: ((Lident | Uident), _, _, dir) :: tokens -> begin
|
| (Symbol "#", _) :: ((Lident dir | Uident dir), _) :: tokens -> begin
|
||||||
match try Some (Hashtbl.find Toploop.directive_table dir) with Not_found -> None with
|
match try Some (Hashtbl.find Toploop.directive_table dir) with Not_found -> None with
|
||||||
| Some (Toploop.Directive_none _) ->
|
| Some (Toploop.Directive_none _) ->
|
||||||
(0, [])
|
(0, [])
|
||||||
|
@ -748,8 +777,8 @@ let complete str =
|
||||||
(0, [])
|
(0, [])
|
||||||
| Some (Toploop.Directive_bool _) -> begin
|
| Some (Toploop.Directive_bool _) -> begin
|
||||||
match tokens with
|
match tokens with
|
||||||
| [(Lident, start, _, id)] ->
|
| [(Lident id, { idx1 = start })] ->
|
||||||
(start, lookup_assoc id [("true", ";;"); ("false", ";;")])
|
(start, lookup_assoc id [("true", phrase_terminator); ("false", phrase_terminator)])
|
||||||
| _ ->
|
| _ ->
|
||||||
(0, [])
|
(0, [])
|
||||||
end
|
end
|
||||||
|
@ -769,32 +798,35 @@ let complete str =
|
||||||
end
|
end
|
||||||
|
|
||||||
(* Completion on identifiers. *)
|
(* Completion on identifiers. *)
|
||||||
| [] ->
|
|
||||||
(0, List.map (fun w -> (w, "")) (String_set.elements (String_set.union !UTop.keywords (Lazy.force !global_names))))
|
|
||||||
| _ ->
|
| _ ->
|
||||||
let tokens = List.rev tokens in
|
match find_context tokens tokens with
|
||||||
match parse_method tokens with
|
|
||||||
| Some (longident, meths, start, meth) ->
|
|
||||||
(start, List.map (fun w -> (w, "")) (lookup meth (methods_of_object longident meths)))
|
|
||||||
| None ->
|
| None ->
|
||||||
match parse_label tokens with
|
(0, [])
|
||||||
| Some (Fun, longident, meths, Optional, start, label) ->
|
| Some [] ->
|
||||||
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (List.filter (function (w, Optional) -> true | (w, Required) -> false) (labels_of_function longident meths))))
|
(0, List.map (fun w -> (w, "")) (String_set.elements (String_set.union !UTop.keywords (Lazy.force !global_names))))
|
||||||
| Some (Fun, longident, meths, Required, start, label) ->
|
| Some tokens ->
|
||||||
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (labels_of_function longident meths)))
|
match parse_method tokens with
|
||||||
| Some (New, longident, meths, Optional, start, label) ->
|
| Some (longident, meths, start, meth) ->
|
||||||
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (List.filter (function (w, Optional) -> true | (w, Required) -> false) (labels_of_newclass longident))))
|
(start, List.map (fun w -> (w, "")) (lookup meth (methods_of_object longident meths)))
|
||||||
| Some (New, longident, meths, Required, start, label) ->
|
|
||||||
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (labels_of_newclass longident)))
|
|
||||||
| None ->
|
| None ->
|
||||||
match parse_longident tokens with
|
match parse_label tokens with
|
||||||
|
| Some (Fun, longident, meths, Optional, start, label) ->
|
||||||
|
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (List.filter (function (w, Optional) -> true | (w, Required) -> false) (labels_of_function longident meths))))
|
||||||
|
| Some (Fun, longident, meths, Required, start, label) ->
|
||||||
|
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (labels_of_function longident meths)))
|
||||||
|
| Some (New, longident, meths, Optional, start, label) ->
|
||||||
|
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (List.filter (function (w, Optional) -> true | (w, Required) -> false) (labels_of_newclass longident))))
|
||||||
|
| Some (New, longident, meths, Required, start, label) ->
|
||||||
|
(start, List.map (fun (w, kind) -> (w, ":")) (lookup_assoc label (labels_of_newclass longident)))
|
||||||
| None ->
|
| None ->
|
||||||
(0, [])
|
match parse_longident tokens with
|
||||||
| Some (Value, None, start, id) ->
|
| None ->
|
||||||
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (String_set.union !UTop.keywords (Lazy.force !global_names)))))
|
(0, [])
|
||||||
| Some (Value, Some longident, start, id) ->
|
| Some (Value, None, start, id) ->
|
||||||
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (names_of_module longident))))
|
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (String_set.union !UTop.keywords (Lazy.force !global_names)))))
|
||||||
| Some (Field, None, start, id) ->
|
| Some (Value, Some longident, start, id) ->
|
||||||
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (Lazy.force !global_fields))))
|
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (names_of_module longident))))
|
||||||
| Some (Field, Some longident, start, id) ->
|
| Some (Field, None, start, id) ->
|
||||||
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (fields_of_module longident))))
|
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (Lazy.force !global_fields))))
|
||||||
|
| Some (Field, Some longident, start, id) ->
|
||||||
|
(start, List.map (fun w -> (w, "")) (lookup id (String_set.elements (fields_of_module longident))))
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
|
|
||||||
(** OCaml completion. *)
|
(** OCaml completion. *)
|
||||||
|
|
||||||
val complete : string -> int * (string * string) list
|
val complete : syntax : UTop.syntax -> phrase_terminator : string -> input : string -> int * (string * string) list
|
||||||
(** [complete str] returns the start of the completed word in [str]
|
(** [complete ~syntax ~phrase_terminator ~input] returns the start
|
||||||
and the list of possible completions with their suffixes. *)
|
of the completed word in [input] and the list of possible
|
||||||
|
completions with their suffixes. *)
|
||||||
|
|
||||||
val reset : unit -> unit
|
val reset : unit -> unit
|
||||||
(** Reset global cache. It must be called before each interactive
|
(** Reset global cache. It must be called before each interactive
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
* This file is a part of utop.
|
* This file is a part of utop.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
val lex_string : ?camlp4 : bool -> string -> (UTop_token.t * int * int * string) list
|
val lex_string : UTop.syntax -> string -> (UTop_token.t * UTop_token.location) list
|
||||||
(** [lex_string str] returns all the tokens contained in [str]. It
|
(** [lex_string syntax str] returns all the tokens contained in
|
||||||
returns a list of [(token, start_index, stop_index,
|
[str]. *)
|
||||||
contents)]. Indexes are in unicode characters.
|
|
||||||
|
|
||||||
If [camlp4] is [true] then quotations are parsed. *)
|
|
||||||
|
|
|
@ -10,7 +10,40 @@
|
||||||
(* Lexer for the OCaml language. *)
|
(* Lexer for the OCaml language. *)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
open Lexing
|
||||||
open UTop_token
|
open UTop_token
|
||||||
|
|
||||||
|
(* Return the size in bytes. *)
|
||||||
|
let lexeme_size lexbuf =
|
||||||
|
lexeme_end lexbuf - lexeme_start lexbuf
|
||||||
|
|
||||||
|
let mkloc idx1 idx2 ofs1 ofs2 = {
|
||||||
|
idx1 = idx1;
|
||||||
|
idx2 = idx2;
|
||||||
|
ofs1 = ofs1;
|
||||||
|
ofs2 = ofs2;
|
||||||
|
}
|
||||||
|
|
||||||
|
(* Only for ascii-only lexemes. *)
|
||||||
|
let lexeme_loc idx lexbuf =
|
||||||
|
let ofs1 = lexeme_start lexbuf and ofs2 = lexeme_end lexbuf in
|
||||||
|
{
|
||||||
|
idx1 = idx;
|
||||||
|
idx2 = idx + (ofs2 - ofs1);
|
||||||
|
ofs1 = ofs1;
|
||||||
|
ofs2 = ofs2;
|
||||||
|
}
|
||||||
|
|
||||||
|
let merge_loc l1 l2 = {
|
||||||
|
idx1 = l1.idx1;
|
||||||
|
idx2 = l2.idx2;
|
||||||
|
ofs1 = l1.ofs1;
|
||||||
|
ofs2 = l2.ofs2;
|
||||||
|
}
|
||||||
|
|
||||||
|
type context =
|
||||||
|
| Toplevel
|
||||||
|
| Antiquot
|
||||||
}
|
}
|
||||||
|
|
||||||
let uchar = ['\x00' - '\x7f'] | _ [ '\x80' - '\xbf' ]*
|
let uchar = ['\x00' - '\x7f'] | _ [ '\x80' - '\xbf' ]*
|
||||||
|
@ -42,51 +75,98 @@ let float_literal =
|
||||||
let symbolchar =
|
let symbolchar =
|
||||||
['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~']
|
['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~']
|
||||||
|
|
||||||
rule token fallback = parse
|
rule tokens syntax context idx = parse
|
||||||
|
| eof
|
||||||
|
{ (idx, None, []) }
|
||||||
| ('\n' | blank)+
|
| ('\n' | blank)+
|
||||||
{ Blanks }
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
| "true"
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
{ Constant }
|
(idx, res, (Blanks, loc) :: l) }
|
||||||
| "false"
|
|
||||||
{ Constant }
|
|
||||||
| lident
|
| lident
|
||||||
{ Lident }
|
{ let src = lexeme lexbuf in
|
||||||
|
let loc = lexeme_loc idx lexbuf in
|
||||||
|
let tok =
|
||||||
|
match syntax, src with
|
||||||
|
| (UTop.Normal | UTop.Camlp4o), ("true" | "false") ->
|
||||||
|
Constant src
|
||||||
|
| _ ->
|
||||||
|
Lident src
|
||||||
|
in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (tok, loc) :: l) }
|
||||||
| uident
|
| uident
|
||||||
{ Uident }
|
{ let src = lexeme lexbuf in
|
||||||
|
let loc = lexeme_loc idx lexbuf in
|
||||||
|
let tok =
|
||||||
|
match syntax, src with
|
||||||
|
| UTop.Camlp4r, "True" ->
|
||||||
|
Constant "true"
|
||||||
|
| UTop.Camlp4r, "False" ->
|
||||||
|
Constant "false"
|
||||||
|
| _ ->
|
||||||
|
Uident src
|
||||||
|
in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (tok, loc) :: l) }
|
||||||
| int_literal "l"
|
| int_literal "l"
|
||||||
{ Constant }
|
|
||||||
| int_literal "L"
|
| int_literal "L"
|
||||||
{ Constant }
|
|
||||||
| int_literal "n"
|
| int_literal "n"
|
||||||
{ Constant }
|
|
||||||
| int_literal
|
| int_literal
|
||||||
{ Constant }
|
|
||||||
| float_literal
|
| float_literal
|
||||||
{ Constant }
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
|
let tok = Constant (lexeme lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (tok, loc) :: l) }
|
||||||
| '"'
|
| '"'
|
||||||
{ String (string lexbuf) }
|
{ let ofs = lexeme_start lexbuf in
|
||||||
|
let idx2, terminated = string (idx + 1) lexbuf in
|
||||||
|
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context idx2 lexbuf in
|
||||||
|
(idx, res, (String terminated, loc) :: l) }
|
||||||
| "'" [^'\'' '\\'] "'"
|
| "'" [^'\'' '\\'] "'"
|
||||||
{ Char }
|
|
||||||
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\'' 'x' '0'-'9'] eof
|
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\'' 'x' '0'-'9'] eof
|
||||||
{ Char }
|
|
||||||
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\''] "'"
|
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\''] "'"
|
||||||
{ Char }
|
|
||||||
| "'\\" (['0'-'9'] ['0'-'9'] | 'x' hexa_char) eof
|
| "'\\" (['0'-'9'] ['0'-'9'] | 'x' hexa_char) eof
|
||||||
{ Char }
|
|
||||||
| "'\\" (['0'-'9'] ['0'-'9'] ['0'-'9'] | 'x' hexa_char hexa_char) eof
|
| "'\\" (['0'-'9'] ['0'-'9'] ['0'-'9'] | 'x' hexa_char hexa_char) eof
|
||||||
{ Char }
|
|
||||||
| "'\\" (['0'-'9'] ['0'-'9'] ['0'-'9'] | 'x' hexa_char hexa_char) "'"
|
| "'\\" (['0'-'9'] ['0'-'9'] ['0'-'9'] | 'x' hexa_char hexa_char) "'"
|
||||||
{ Char }
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (Char, loc) :: l) }
|
||||||
| "'\\" uchar
|
| "'\\" uchar
|
||||||
{ Error }
|
{ let loc = mkloc idx (idx + 3) (lexeme_start lexbuf) (lexeme_end lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (Error, loc) :: l) }
|
||||||
|
| "(*)"
|
||||||
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (Comment (Comment_reg, true), loc) :: l) }
|
||||||
|
| "(**)"
|
||||||
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (Comment (Comment_doc, true), loc) :: l) }
|
||||||
| "(**"
|
| "(**"
|
||||||
{ Doc (comment 0 lexbuf) }
|
{ let ofs = lexeme_start lexbuf in
|
||||||
|
let idx2, terminated = comment (idx + 3) 0 lexbuf in
|
||||||
|
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context idx2 lexbuf in
|
||||||
|
(idx, res, (Comment (Comment_doc, terminated), loc) :: l) }
|
||||||
| "(*"
|
| "(*"
|
||||||
{ Comment (comment 0 lexbuf) }
|
{ let ofs = lexeme_start lexbuf in
|
||||||
|
let idx2, terminated = comment (idx + 2) 0 lexbuf in
|
||||||
|
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context idx2 lexbuf in
|
||||||
|
(idx, res, (Comment (Comment_reg, terminated), loc) :: l) }
|
||||||
| ""
|
| ""
|
||||||
{ fallback lexbuf }
|
{ if syntax = UTop.Normal then
|
||||||
|
symbol syntax context idx lexbuf
|
||||||
|
else
|
||||||
|
match context with
|
||||||
|
| Toplevel ->
|
||||||
|
camlp4_toplevel syntax context idx lexbuf
|
||||||
|
| Antiquot ->
|
||||||
|
camlp4_antiquot syntax context idx lexbuf }
|
||||||
|
|
||||||
and token_fallback = parse
|
and symbol syntax context idx = parse
|
||||||
| "(" | ")"
|
| "(" | ")"
|
||||||
| "[" | "]"
|
| "[" | "]"
|
||||||
| "{" | "}"
|
| "{" | "}"
|
||||||
|
@ -95,71 +175,114 @@ and token_fallback = parse
|
||||||
| ","
|
| ","
|
||||||
| ";" | ";;"
|
| ";" | ";;"
|
||||||
| symbolchar+
|
| symbolchar+
|
||||||
{ Symbol }
|
{ let loc = lexeme_loc idx lexbuf in
|
||||||
|
let tok = Symbol (lexeme lexbuf) in
|
||||||
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
|
(idx, res, (tok, loc) :: l) }
|
||||||
| uchar
|
| uchar
|
||||||
{ Error }
|
{ let loc = mkloc idx (idx + 1) (lexeme_start lexbuf) (lexeme_end lexbuf) in
|
||||||
| eof
|
let idx, res, l = tokens syntax context loc.idx2 lexbuf in
|
||||||
{ raise End_of_file }
|
(idx, res, (Error, loc) :: l) }
|
||||||
|
|
||||||
and token_fallback_camlp4 = parse
|
and camlp4_toplevel syntax context idx = parse
|
||||||
| '<' (':' ident)? ('@' lident)? '<'
|
| '<' (':' ident)? ('@' lident)? '<'
|
||||||
{ Quotation (quotation lexbuf) }
|
{ let ofs = lexeme_start lexbuf in
|
||||||
|
let idx2, items, terminated = quotation syntax 0 idx (idx + lexeme_size lexbuf) (lexeme_start lexbuf) lexbuf in
|
||||||
|
let ofs2 = lexeme_end lexbuf in
|
||||||
|
let idx3, res, l = tokens syntax context idx2 lexbuf in
|
||||||
|
(idx3, res, (Quotation (items, terminated), mkloc idx idx2 ofs ofs2) :: l) }
|
||||||
| ""
|
| ""
|
||||||
{ token_fallback lexbuf }
|
{ symbol syntax context idx lexbuf }
|
||||||
|
|
||||||
and comment depth = parse
|
and camlp4_antiquot syntax context idx = parse
|
||||||
|
| '$'
|
||||||
|
{ (idx + 1, Some (lexeme_loc idx lexbuf), []) }
|
||||||
|
| ""
|
||||||
|
{ camlp4_toplevel syntax context idx lexbuf }
|
||||||
|
|
||||||
|
and comment idx depth = parse
|
||||||
| "(*"
|
| "(*"
|
||||||
{ comment (depth + 1) lexbuf }
|
{ comment (idx + 2) (depth + 1) lexbuf }
|
||||||
| "*)"
|
| "*)"
|
||||||
{ if depth > 0 then comment (depth - 1) lexbuf else true }
|
{ if depth = 0 then
|
||||||
|
(idx + 2, true)
|
||||||
|
else
|
||||||
|
comment (idx + 2) (depth - 1) lexbuf }
|
||||||
| '"'
|
| '"'
|
||||||
{ string lexbuf && comment depth lexbuf }
|
{ let idx, terminated = string (idx + 1) lexbuf in
|
||||||
|
if terminated then
|
||||||
|
comment idx depth lexbuf
|
||||||
|
else
|
||||||
|
(idx, false) }
|
||||||
| uchar
|
| uchar
|
||||||
{ comment depth lexbuf }
|
{ comment (idx + 1) depth lexbuf }
|
||||||
| eof
|
| eof
|
||||||
{ false }
|
{ (idx, false) }
|
||||||
|
|
||||||
and string = parse
|
and string idx = parse
|
||||||
| '"'
|
| '"'
|
||||||
{ true }
|
{ (idx + 1, true) }
|
||||||
| "\\\""
|
| "\\\""
|
||||||
{ string lexbuf }
|
{ string (idx + 2) lexbuf }
|
||||||
| uchar
|
| uchar
|
||||||
{ string lexbuf }
|
{ string (idx + 1) lexbuf }
|
||||||
| eof
|
| eof
|
||||||
{ false }
|
{ (idx, false) }
|
||||||
|
|
||||||
and quotation = parse
|
and quotation syntax depth idx1 idx2 ofs1 = parse
|
||||||
|
| '<' (':' ident)? ('@' lident)? '<'
|
||||||
|
{ quotation syntax (depth + 1) idx1 (idx2 + lexeme_size lexbuf) ofs1 lexbuf }
|
||||||
| ">>"
|
| ">>"
|
||||||
{ true }
|
{ if depth = 0 then
|
||||||
|
let loc = mkloc idx1 (idx2 + 2) ofs1 (lexeme_end lexbuf) in
|
||||||
|
(idx2 + 2, [(Quot_data, loc)], true)
|
||||||
|
else
|
||||||
|
quotation syntax (depth - 1) idx1 (idx2 + 2) ofs1 lexbuf }
|
||||||
| '$'
|
| '$'
|
||||||
{ antiquotation lexbuf }
|
{ let quot_data_loc =
|
||||||
|
if idx1 = idx2 then
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some (mkloc idx1 idx2 ofs1 (lexeme_start lexbuf))
|
||||||
|
in
|
||||||
|
let opening_loc = lexeme_loc idx2 lexbuf in
|
||||||
|
let idx, name = quotation_name (idx2 + 1) lexbuf in
|
||||||
|
let idx, closing_loc, items = tokens syntax Antiquot idx lexbuf in
|
||||||
|
let anti = {
|
||||||
|
a_opening = opening_loc;
|
||||||
|
a_closing = closing_loc;
|
||||||
|
a_name = name;
|
||||||
|
a_contents = items;
|
||||||
|
} in
|
||||||
|
let ofs = lexeme_end lexbuf in
|
||||||
|
let loc = mkloc opening_loc.idx1 idx opening_loc.ofs2 ofs in
|
||||||
|
let idx, quot_items, terminated = quotation syntax depth idx idx ofs lexbuf in
|
||||||
|
let quot_items = (Quot_anti anti, loc) :: quot_items in
|
||||||
|
match quot_data_loc with
|
||||||
|
| Some loc ->
|
||||||
|
(idx, (Quot_data, loc) :: quot_items, terminated)
|
||||||
|
| None ->
|
||||||
|
(idx, quot_items, terminated) }
|
||||||
| uchar
|
| uchar
|
||||||
{ quotation lexbuf }
|
{ quotation syntax depth idx1 (idx2 + 1) ofs1 lexbuf }
|
||||||
| eof
|
| eof
|
||||||
{ false }
|
{ if idx1 = idx2 then
|
||||||
|
(idx2, [], false)
|
||||||
|
else
|
||||||
|
let loc = mkloc idx1 idx2 ofs1 (lexeme_end lexbuf) in
|
||||||
|
(idx2, [(Quot_data, loc)], false) }
|
||||||
|
|
||||||
and antiquotation = parse
|
and quotation_name idx = parse
|
||||||
| '$'
|
| '`'? (identchar*|['.' '!']+) ':'
|
||||||
{ quotation lexbuf }
|
{ let len = lexeme_size lexbuf in
|
||||||
| eof
|
let ofs = lexeme_start lexbuf in
|
||||||
{ false }
|
(idx + len, Some (mkloc idx (idx + len - 1) ofs (ofs + len - 1),
|
||||||
|
mkloc (idx + len - 1) (idx + len) (ofs + len - 1) (ofs + len))) }
|
||||||
| ""
|
| ""
|
||||||
{ ignore (token token_fallback_camlp4 lexbuf); antiquotation lexbuf }
|
{ (idx, None) }
|
||||||
|
|
||||||
{
|
{
|
||||||
let lex_string ?(camlp4=false) str =
|
let lex_string syntax str =
|
||||||
let fallback = if camlp4 then token_fallback_camlp4 else token_fallback in
|
let _, _, items = tokens syntax Toplevel 0 (Lexing.from_string str) in
|
||||||
let lexbuf = Lexing.from_string str in
|
items
|
||||||
let rec loop idx ofs_a =
|
|
||||||
match try Some (token fallback lexbuf) with End_of_file -> None with
|
|
||||||
| Some token ->
|
|
||||||
let ofs_b = Lexing.lexeme_end lexbuf in
|
|
||||||
let src = String.sub str ofs_a (ofs_b - ofs_a) in
|
|
||||||
let idx' = idx + Zed_utf8.length src in
|
|
||||||
(token, idx, idx', src) :: loop idx' ofs_b
|
|
||||||
| None ->
|
|
||||||
[]
|
|
||||||
in
|
|
||||||
loop 0 0
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,13 +122,13 @@ class read_phrase ~term = object(self)
|
||||||
let styled, position = super#stylise last in
|
let styled, position = super#stylise last in
|
||||||
|
|
||||||
(* Syntax highlighting *)
|
(* Syntax highlighting *)
|
||||||
let stylise start stop token_style =
|
let stylise loc token_style =
|
||||||
for i = start to stop - 1 do
|
for i = loc.idx1 to loc.idx2 - 1 do
|
||||||
let ch, style = styled.(i) in
|
let ch, style = styled.(i) in
|
||||||
styled.(i) <- (ch, LTerm_style.merge token_style style)
|
styled.(i) <- (ch, LTerm_style.merge token_style style)
|
||||||
done
|
done
|
||||||
in
|
in
|
||||||
UTop_styles.stylise stylise (UTop_lexer.lex_string ~camlp4:(UTop.get_camlp4 ()) (LTerm_text.to_string styled));
|
UTop_styles.stylise stylise (UTop_lexer.lex_string (UTop.get_syntax ()) (LTerm_text.to_string styled));
|
||||||
|
|
||||||
if not last then
|
if not last then
|
||||||
(* Parenthesis matching. *)
|
(* Parenthesis matching. *)
|
||||||
|
@ -151,7 +151,12 @@ class read_phrase ~term = object(self)
|
||||||
(styled, position)
|
(styled, position)
|
||||||
|
|
||||||
method completion =
|
method completion =
|
||||||
let pos, words = UTop_complete.complete (Zed_rope.to_string self#input_prev) in
|
let pos, words =
|
||||||
|
UTop_complete.complete
|
||||||
|
~syntax:(UTop.get_syntax ())
|
||||||
|
~phrase_terminator:(UTop.get_phrase_terminator ())
|
||||||
|
~input:(Zed_rope.to_string self#input_prev)
|
||||||
|
in
|
||||||
self#set_completion pos words
|
self#set_completion pos words
|
||||||
|
|
||||||
initializer
|
initializer
|
||||||
|
@ -207,13 +212,13 @@ let print_out_phrase term printer pp out_phrase =
|
||||||
Format.pp_print_flush pp ();
|
Format.pp_print_flush pp ();
|
||||||
let string = fix_string (Buffer.contents buffer) in
|
let string = fix_string (Buffer.contents buffer) in
|
||||||
let styled = LTerm_text.of_string string in
|
let styled = LTerm_text.of_string string in
|
||||||
let stylise start stop token_style =
|
let stylise loc token_style =
|
||||||
for i = start to stop - 1 do
|
for i = loc.idx1 to loc.idx2 - 1 do
|
||||||
let ch, style = styled.(i) in
|
let ch, style = styled.(i) in
|
||||||
styled.(i) <- (ch, LTerm_style.merge token_style style)
|
styled.(i) <- (ch, LTerm_style.merge token_style style)
|
||||||
done
|
done
|
||||||
in
|
in
|
||||||
UTop_styles.stylise stylise (UTop_lexer.lex_string string);
|
UTop_styles.stylise stylise (UTop_lexer.lex_string (UTop.get_syntax ()) string);
|
||||||
Lwt_main.run (LTerm.fprints term styled)
|
Lwt_main.run (LTerm.fprints term styled)
|
||||||
|
|
||||||
(* +-----------------------------------------------------------------+
|
(* +-----------------------------------------------------------------+
|
||||||
|
@ -579,7 +584,12 @@ module Emacs(M : sig end) = struct
|
||||||
loop ()
|
loop ()
|
||||||
| Some ("complete", _) ->
|
| Some ("complete", _) ->
|
||||||
let input = read_data () in
|
let input = read_data () in
|
||||||
let start, words = UTop_complete.complete input in
|
let start, words =
|
||||||
|
UTop_complete.complete
|
||||||
|
~syntax:(UTop.get_syntax ())
|
||||||
|
~phrase_terminator:(UTop.get_phrase_terminator ())
|
||||||
|
~input
|
||||||
|
in
|
||||||
let words = List.map fst words in
|
let words = List.map fst words in
|
||||||
let prefix = LTerm_read_line.common_prefix words in
|
let prefix = LTerm_read_line.common_prefix words in
|
||||||
let index = String.length input - start in
|
let index = String.length input - start in
|
||||||
|
|
|
@ -91,209 +91,103 @@ let load () =
|
||||||
| Unix.Unix_error (error, func, arg) ->
|
| Unix.Unix_error (error, func, arg) ->
|
||||||
Lwt_log.error_f "cannot load styles from %S: %s: %s" fn func (Unix.error_message error)
|
Lwt_log.error_f "cannot load styles from %S: %s: %s" fn func (Unix.error_message error)
|
||||||
|
|
||||||
|
let rec stylise_filter_layout stylise tokens =
|
||||||
|
match tokens with
|
||||||
|
| [] ->
|
||||||
|
[]
|
||||||
|
| (Comment (Comment_reg, _), loc) :: tokens ->
|
||||||
|
stylise loc styles.style_comment;
|
||||||
|
stylise_filter_layout stylise tokens
|
||||||
|
| (Comment (Comment_doc, _), loc) :: tokens ->
|
||||||
|
stylise loc styles.style_doc;
|
||||||
|
stylise_filter_layout stylise tokens
|
||||||
|
| (Blanks, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_blanks;
|
||||||
|
stylise_filter_layout stylise tokens
|
||||||
|
| x :: tokens ->
|
||||||
|
x :: stylise_filter_layout stylise tokens
|
||||||
|
|
||||||
|
let rec stylise_rec stylise tokens =
|
||||||
|
match tokens with
|
||||||
|
| [] ->
|
||||||
|
()
|
||||||
|
| (Symbol _, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_symbol;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Lident id, loc) :: tokens ->
|
||||||
|
stylise loc
|
||||||
|
(if String_set.mem id !UTop.keywords then
|
||||||
|
styles.style_keyword
|
||||||
|
else
|
||||||
|
styles.style_ident);
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Uident id, loc) :: tokens when String_set.mem id !UTop.keywords ->
|
||||||
|
stylise loc styles.style_keyword;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Uident id, loc1) :: (Symbol ".", loc2) :: tokens ->
|
||||||
|
stylise loc1 styles.style_module;
|
||||||
|
stylise loc2 styles.style_symbol;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Uident id, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_ident;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Constant _, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_constant;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Char, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_char;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (String _, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_string;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Quotation (items, _), _) :: tokens ->
|
||||||
|
stylise_quotation_items stylise items;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| (Error, loc) :: tokens ->
|
||||||
|
stylise loc styles.style_error;
|
||||||
|
stylise_rec stylise tokens
|
||||||
|
| ((Comment _ | Blanks), _) :: _ ->
|
||||||
|
assert false
|
||||||
|
|
||||||
|
and stylise_quotation_items stylise items =
|
||||||
|
match items with
|
||||||
|
| [] ->
|
||||||
|
()
|
||||||
|
| (Quot_data, loc) :: items ->
|
||||||
|
stylise loc styles.style_quotation;
|
||||||
|
stylise_quotation_items stylise items
|
||||||
|
| (Quot_anti anti, _) :: items ->
|
||||||
|
stylise anti.a_opening styles.style_symbol;
|
||||||
|
(match anti.a_name with
|
||||||
|
| None ->
|
||||||
|
()
|
||||||
|
| Some (loc1, loc2) ->
|
||||||
|
stylise loc1 styles.style_module;
|
||||||
|
stylise loc2 styles.style_symbol);
|
||||||
|
let tokens = stylise_filter_layout stylise anti.a_contents in
|
||||||
|
stylise_rec stylise tokens;
|
||||||
|
(match anti.a_closing with
|
||||||
|
| None ->
|
||||||
|
()
|
||||||
|
| Some loc ->
|
||||||
|
stylise loc styles.style_symbol);
|
||||||
|
stylise_quotation_items stylise items
|
||||||
|
|
||||||
let stylise stylise tokens =
|
let stylise stylise tokens =
|
||||||
let rec loop tokens =
|
let tokens = stylise_filter_layout stylise tokens in
|
||||||
match tokens with
|
match tokens with
|
||||||
| [] ->
|
| (Symbol "#", loc) :: tokens -> begin
|
||||||
()
|
stylise loc styles.style_directive;
|
||||||
| (token, start, stop, src) :: rest ->
|
match tokens with
|
||||||
match token with
|
| ((Lident id | Uident id), loc) :: tokens ->
|
||||||
| Symbol ->
|
stylise loc
|
||||||
stylise start stop styles.style_symbol;
|
(if String_set.mem id !UTop.keywords then
|
||||||
loop rest
|
styles.style_keyword
|
||||||
| Lident ->
|
else
|
||||||
stylise start stop
|
styles.style_directive);
|
||||||
(if String_set.mem src !UTop.keywords then
|
stylise_rec stylise tokens
|
||||||
styles.style_keyword
|
| tokens ->
|
||||||
else
|
stylise_rec stylise tokens
|
||||||
styles.style_ident);
|
end
|
||||||
loop rest
|
| tokens ->
|
||||||
| Uident ->
|
stylise_rec stylise tokens
|
||||||
if String_set.mem src !UTop.keywords then begin
|
|
||||||
stylise start stop styles.style_keyword;
|
|
||||||
loop rest
|
|
||||||
end else
|
|
||||||
loop_after_uident start stop rest
|
|
||||||
| Constant ->
|
|
||||||
stylise start stop styles.style_constant;
|
|
||||||
loop rest
|
|
||||||
| Char ->
|
|
||||||
stylise start stop styles.style_char;
|
|
||||||
loop rest
|
|
||||||
| String _ ->
|
|
||||||
stylise start stop styles.style_string;
|
|
||||||
loop rest
|
|
||||||
| Quotation _ ->
|
|
||||||
stylise start stop styles.style_quotation;
|
|
||||||
loop rest
|
|
||||||
| Comment _ ->
|
|
||||||
stylise start stop styles.style_comment;
|
|
||||||
loop rest
|
|
||||||
| Doc _ ->
|
|
||||||
stylise start stop styles.style_doc;
|
|
||||||
loop rest
|
|
||||||
| Blanks ->
|
|
||||||
stylise start stop styles.style_blanks;
|
|
||||||
loop rest
|
|
||||||
| Error ->
|
|
||||||
stylise start stop styles.style_error;
|
|
||||||
loop rest
|
|
||||||
and loop_after_uident uid_start uid_stop tokens =
|
|
||||||
match tokens with
|
|
||||||
| [] ->
|
|
||||||
()
|
|
||||||
| (token, start, stop, src) :: rest ->
|
|
||||||
match token with
|
|
||||||
| Symbol ->
|
|
||||||
if src = "." then
|
|
||||||
stylise uid_start uid_stop styles.style_module
|
|
||||||
else
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_symbol;
|
|
||||||
loop rest
|
|
||||||
| Lident ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop
|
|
||||||
(if String_set.mem src !UTop.keywords then
|
|
||||||
styles.style_keyword
|
|
||||||
else
|
|
||||||
styles.style_ident);
|
|
||||||
loop rest
|
|
||||||
| Uident ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
if String_set.mem src !UTop.keywords then begin
|
|
||||||
stylise start stop styles.style_keyword;
|
|
||||||
loop rest
|
|
||||||
end else
|
|
||||||
loop_after_uident start stop rest
|
|
||||||
| Constant ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_constant;
|
|
||||||
loop rest
|
|
||||||
| Char ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_char;
|
|
||||||
loop rest
|
|
||||||
| String _ ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_string;
|
|
||||||
loop rest
|
|
||||||
| Quotation _ ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_quotation;
|
|
||||||
loop rest
|
|
||||||
| Comment _ ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_comment;
|
|
||||||
loop_after_uident uid_start uid_stop rest
|
|
||||||
| Doc _ ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_doc;
|
|
||||||
loop_after_uident uid_start uid_stop rest
|
|
||||||
| Blanks ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_blanks;
|
|
||||||
loop_after_uident uid_start uid_stop rest
|
|
||||||
| Error ->
|
|
||||||
stylise uid_start uid_stop styles.style_ident;
|
|
||||||
stylise start stop styles.style_error;
|
|
||||||
loop rest
|
|
||||||
and loop_sharp tokens =
|
|
||||||
match tokens with
|
|
||||||
| [] ->
|
|
||||||
()
|
|
||||||
| (token, start, stop, src) :: rest ->
|
|
||||||
match token with
|
|
||||||
| Symbol ->
|
|
||||||
if src = "#" then begin
|
|
||||||
stylise start stop styles.style_directive;
|
|
||||||
loop_directive rest
|
|
||||||
end else begin
|
|
||||||
stylise start stop styles.style_symbol;
|
|
||||||
loop rest
|
|
||||||
end
|
|
||||||
| Lident ->
|
|
||||||
stylise start stop
|
|
||||||
(if String_set.mem src !UTop.keywords then
|
|
||||||
styles.style_keyword
|
|
||||||
else
|
|
||||||
styles.style_ident);
|
|
||||||
loop rest
|
|
||||||
| Uident ->
|
|
||||||
if String_set.mem src !UTop.keywords then begin
|
|
||||||
stylise start stop styles.style_keyword;
|
|
||||||
loop rest
|
|
||||||
end else
|
|
||||||
loop_after_uident start stop rest
|
|
||||||
| Constant ->
|
|
||||||
stylise start stop styles.style_constant;
|
|
||||||
loop rest
|
|
||||||
| Char ->
|
|
||||||
stylise start stop styles.style_char;
|
|
||||||
loop rest
|
|
||||||
| String _ ->
|
|
||||||
stylise start stop styles.style_string;
|
|
||||||
loop rest
|
|
||||||
| Quotation _ ->
|
|
||||||
stylise start stop styles.style_quotation;
|
|
||||||
loop rest
|
|
||||||
| Comment _ ->
|
|
||||||
stylise start stop styles.style_comment;
|
|
||||||
loop_sharp rest
|
|
||||||
| Doc _ ->
|
|
||||||
stylise start stop styles.style_doc;
|
|
||||||
loop_sharp rest
|
|
||||||
| Blanks ->
|
|
||||||
stylise start stop styles.style_blanks;
|
|
||||||
loop_sharp rest
|
|
||||||
| Error ->
|
|
||||||
stylise start stop styles.style_error;
|
|
||||||
loop rest
|
|
||||||
and loop_directive tokens =
|
|
||||||
match tokens with
|
|
||||||
| [] ->
|
|
||||||
()
|
|
||||||
| (token, start, stop, src) :: rest ->
|
|
||||||
match token with
|
|
||||||
| Symbol ->
|
|
||||||
stylise start stop styles.style_symbol;
|
|
||||||
loop rest
|
|
||||||
| Lident ->
|
|
||||||
stylise start stop
|
|
||||||
(if String_set.mem src !UTop.keywords then
|
|
||||||
styles.style_keyword
|
|
||||||
else
|
|
||||||
styles.style_directive);
|
|
||||||
loop rest
|
|
||||||
| Uident ->
|
|
||||||
if String_set.mem src !UTop.keywords then begin
|
|
||||||
stylise start stop styles.style_keyword;
|
|
||||||
loop rest
|
|
||||||
end else
|
|
||||||
loop_after_uident start stop rest
|
|
||||||
| Constant ->
|
|
||||||
stylise start stop styles.style_constant;
|
|
||||||
loop rest
|
|
||||||
| Char ->
|
|
||||||
stylise start stop styles.style_char;
|
|
||||||
loop rest
|
|
||||||
| String _ ->
|
|
||||||
stylise start stop styles.style_string;
|
|
||||||
loop rest
|
|
||||||
| Quotation _ ->
|
|
||||||
stylise start stop styles.style_quotation;
|
|
||||||
loop rest
|
|
||||||
| Comment _ ->
|
|
||||||
stylise start stop styles.style_comment;
|
|
||||||
loop_directive rest
|
|
||||||
| Doc _ ->
|
|
||||||
stylise start stop styles.style_doc;
|
|
||||||
loop_directive rest
|
|
||||||
| Blanks ->
|
|
||||||
stylise start stop styles.style_blanks;
|
|
||||||
loop_directive rest
|
|
||||||
| Error ->
|
|
||||||
stylise start stop styles.style_error;
|
|
||||||
loop rest
|
|
||||||
in
|
|
||||||
loop_sharp tokens
|
|
||||||
|
|
|
@ -37,6 +37,6 @@ val styles : styles
|
||||||
val load : unit -> unit Lwt.t
|
val load : unit -> unit Lwt.t
|
||||||
(** Load resources into [styles]. *)
|
(** Load resources into [styles]. *)
|
||||||
|
|
||||||
val stylise : (int -> int -> LTerm_style.t -> unit) -> (UTop_token.t * int * int * string) list -> unit
|
val stylise : (UTop_token.location -> LTerm_style.t -> unit) -> (UTop_token.t * UTop_token.location) list -> unit
|
||||||
(** [stylise apply tokens] calls [apply] on all tokens boundary with
|
(** [stylise apply tokens] calls [apply] on all token locations with
|
||||||
the associated style. *)
|
the associated style. *)
|
||||||
|
|
|
@ -7,17 +7,55 @@
|
||||||
* This file is a part of utop.
|
* This file is a part of utop.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** Type of tokens. Tokens with a boolean parameter takes as argument
|
(** Tokens.
|
||||||
wheter the token is terminated or not. *)
|
|
||||||
|
The type of tokens is semi-structured: parentheses construct and
|
||||||
|
quotations are nested and others tokens are flat list. *)
|
||||||
|
|
||||||
|
(** Locations in the source string, which is encoded in UTF-8. *)
|
||||||
|
type location = {
|
||||||
|
idx1 : int;
|
||||||
|
(** Start position in unicode characters. *)
|
||||||
|
idx2 : int;
|
||||||
|
(** Stop position in unicode characters. *)
|
||||||
|
ofs1 : int;
|
||||||
|
(** Start position in bytes. *)
|
||||||
|
ofs2 : int;
|
||||||
|
(** Stop position in bytes. *)
|
||||||
|
}
|
||||||
|
|
||||||
type t =
|
type t =
|
||||||
| Symbol
|
| Symbol of string
|
||||||
| Lident
|
| Lident of string
|
||||||
| Uident
|
| Uident of string
|
||||||
| Constant
|
| Constant of string
|
||||||
| Char
|
| Char
|
||||||
| String of bool
|
| String of bool
|
||||||
| Quotation of bool
|
(** [String terminated]. *)
|
||||||
| Comment of bool
|
| Comment of comment_kind * bool
|
||||||
| Doc of bool
|
(** [Comment (kind, terminated)]. *)
|
||||||
| Blanks
|
| Blanks
|
||||||
| Error
|
| Error
|
||||||
|
| Quotation of (quotation_item * location) list * bool
|
||||||
|
(** [Quotation (items, terminated)]. *)
|
||||||
|
|
||||||
|
and comment_kind =
|
||||||
|
| Comment_reg
|
||||||
|
(** Regular comment. *)
|
||||||
|
| Comment_doc
|
||||||
|
(** Documentation comment. *)
|
||||||
|
|
||||||
|
and quotation_item =
|
||||||
|
| Quot_data
|
||||||
|
| Quot_anti of antiquotation
|
||||||
|
|
||||||
|
and antiquotation = {
|
||||||
|
a_opening : location;
|
||||||
|
(** Location of the opening [$]. *)
|
||||||
|
a_closing : location option;
|
||||||
|
(** Location of the closing [$]. *)
|
||||||
|
a_name : (location * location) option;
|
||||||
|
(** Location of the name and colon if any. *)
|
||||||
|
a_contents : (t * location) list;
|
||||||
|
(** Contents of the location. *)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue