#156: start of support for quoted strings
This commit is contained in:
parent
b63e0f9225
commit
fd7c663264
|
@ -74,7 +74,7 @@ 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) | 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 id | Lident id), { idx1 = start }) :: tokens ->
|
| ((Uident id | Lident id), { idx1 = start }) :: tokens ->
|
||||||
|
@ -847,23 +847,23 @@ let complete ~syntax ~phrase_terminator ~input =
|
||||||
(start, lookup_assoc src (list_directives phrase_terminator))
|
(start, lookup_assoc src (list_directives phrase_terminator))
|
||||||
|
|
||||||
(* Complete with ";;" when possible. *)
|
(* Complete with ";;" when possible. *)
|
||||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, { idx2 = stop })]
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String (_, true), { idx2 = stop })]
|
||||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, _); (Blanks, { idx2 = stop })] ->
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String (_, true), _); (Blanks, { idx2 = stop })] ->
|
||||||
(stop, [(phrase_terminator, "")])
|
(stop, [(phrase_terminator, "")])
|
||||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, _); (Symbol sym, { idx1 = start })] ->
|
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String (_, true), _); (Symbol sym, { idx1 = start })] ->
|
||||||
if Zed_utf8.starts_with phrase_terminator sym then
|
if Zed_utf8.starts_with phrase_terminator sym then
|
||||||
(start, [(phrase_terminator, "")])
|
(start, [(phrase_terminator, "")])
|
||||||
else
|
else
|
||||||
(0, [])
|
(0, [])
|
||||||
|
|
||||||
(* Completion on #require. *)
|
(* Completion on #require. *)
|
||||||
| [(Symbol "#", _); (Lident "require", _); (String false, loc)] ->
|
| [(Symbol "#", _); (Lident "require", _); (String (tlen, false), loc)] ->
|
||||||
let pkg = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let pkg = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||||
let pkgs = lookup pkg (Fl_package_base.list_packages ()) in
|
let pkgs = lookup pkg (Fl_package_base.list_packages ()) in
|
||||||
(loc.idx1 + 1, List.map (fun pkg -> (pkg, "\"" ^ phrase_terminator)) (List.sort compare pkgs))
|
(loc.idx1 + 1, List.map (fun pkg -> (pkg, "\"" ^ phrase_terminator)) (List.sort compare pkgs))
|
||||||
|
|
||||||
| [(Symbol "#", _); (Lident "typeof", _); (String false, loc)] ->
|
| [(Symbol "#", _); (Lident "typeof", _); (String (tlen, false), loc)] ->
|
||||||
let prefix = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let prefix = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||||
begin match Longident.parse prefix with
|
begin match Longident.parse prefix with
|
||||||
| Longident.Ldot (lident, last_prefix) ->
|
| Longident.Ldot (lident, last_prefix) ->
|
||||||
let set = names_of_module lident in
|
let set = names_of_module lident in
|
||||||
|
@ -877,8 +877,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
||||||
end
|
end
|
||||||
|
|
||||||
(* Completion on #load. *)
|
(* Completion on #load. *)
|
||||||
| [(Symbol "#", _); (Lident ("load" | "load_rec"), _); (String false, loc)] ->
|
| [(Symbol "#", _); (Lident ("load" | "load_rec"), _); (String (tlen, false), loc)] ->
|
||||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) 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
|
||||||
|
@ -898,8 +898,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
||||||
|
|
||||||
#if OCAML_VERSION >= (4, 02, 0)
|
#if OCAML_VERSION >= (4, 02, 0)
|
||||||
(* Completion on #ppx. *)
|
(* Completion on #ppx. *)
|
||||||
| [(Symbol "#", _); (Lident ("ppx"), _); (String false, loc)] ->
|
| [(Symbol "#", _); (Lident ("ppx"), _); (String (tlen, false), loc)] ->
|
||||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||||
let filter ~dir_ok name =
|
let filter ~dir_ok name =
|
||||||
try
|
try
|
||||||
Unix.access name [Unix.X_OK];
|
Unix.access name [Unix.X_OK];
|
||||||
|
@ -928,8 +928,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
(* Completion on #use. *)
|
(* Completion on #use. *)
|
||||||
| [(Symbol "#", _); (Lident "use", _); (String false, loc)] ->
|
| [(Symbol "#", _); (Lident "use", _); (String (tlen, false), loc)] ->
|
||||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) 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 ->
|
||||||
|
@ -955,8 +955,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
||||||
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\"" ^ phrase_terminator)) 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, loc)] ->
|
| [(Symbol "#", _); (Lident ("cd" | "directory"), _); (String (tlen, false), loc)] ->
|
||||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) 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
|
||||||
|
|
|
@ -117,7 +117,13 @@ rule tokens syntax context idx acc = parse
|
||||||
{ let ofs = lexeme_start lexbuf in
|
{ let ofs = lexeme_start lexbuf in
|
||||||
let idx2, terminated = string (idx + 1) lexbuf in
|
let idx2, terminated = string (idx + 1) lexbuf in
|
||||||
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
||||||
tokens syntax context idx2 ((String terminated, loc) :: acc) lexbuf }
|
tokens syntax context idx2 ((String (1, terminated), loc) :: acc) lexbuf }
|
||||||
|
| '{' (lowercase* as tag) '|'
|
||||||
|
{ let ofs = lexeme_start lexbuf in
|
||||||
|
let delim_len = String.length tag + 2 in
|
||||||
|
let idx2, terminated = quoted_string (idx + delim_len) tag lexbuf in
|
||||||
|
let loc = mkloc idx idx2 ofs (lexeme_end lexbuf) in
|
||||||
|
tokens syntax context idx2 ((String (delim_len, terminated), loc) :: acc) lexbuf }
|
||||||
| "'" [^'\'' '\\'] "'"
|
| "'" [^'\'' '\\'] "'"
|
||||||
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\'' 'x' '0'-'9'] eof
|
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\'' 'x' '0'-'9'] eof
|
||||||
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\''] "'"
|
| "'\\" ['\\' '"' 'n' 't' 'b' 'r' ' ' '\''] "'"
|
||||||
|
@ -217,6 +223,18 @@ and string idx = parse
|
||||||
| eof
|
| eof
|
||||||
{ (idx, false) }
|
{ (idx, false) }
|
||||||
|
|
||||||
|
and quoted_string idx tag = parse
|
||||||
|
| '|' (lowercase* as tag2) '}'
|
||||||
|
{ let idx = idx + 2 + String.length tag2 in
|
||||||
|
if tag = tag2 then
|
||||||
|
(idx, true)
|
||||||
|
else
|
||||||
|
quoted_string idx tag lexbuf }
|
||||||
|
| eof
|
||||||
|
{ (idx, false) }
|
||||||
|
| uchar
|
||||||
|
{ quoted_string (idx + 1) tag lexbuf }
|
||||||
|
|
||||||
and quotation syntax depth idx1 idx2 ofs1 = parse
|
and quotation syntax depth idx1 idx2 ofs1 = parse
|
||||||
| '<' (':' ident)? ('@' lident)? '<'
|
| '<' (':' ident)? ('@' lident)? '<'
|
||||||
{ quotation syntax (depth + 1) idx1 (idx2 + lexeme_size lexbuf) ofs1 lexbuf }
|
{ quotation syntax (depth + 1) idx1 (idx2 + lexeme_size lexbuf) ofs1 lexbuf }
|
||||||
|
|
|
@ -30,8 +30,8 @@ type t =
|
||||||
| Uident of string
|
| Uident of string
|
||||||
| Constant of string
|
| Constant of string
|
||||||
| Char
|
| Char
|
||||||
| String of bool
|
| String of int * bool
|
||||||
(** [String terminated]. *)
|
(** [String (quote_size, terminated)]. *)
|
||||||
| Comment of comment_kind * bool
|
| Comment of comment_kind * bool
|
||||||
(** [Comment (kind, terminated)]. *)
|
(** [Comment (kind, terminated)]. *)
|
||||||
| Blanks
|
| Blanks
|
||||||
|
|
Loading…
Reference in New Issue