#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))
|
||||
in
|
||||
match tokens with
|
||||
| ((Comment (_, false) | String false | Quotation (_, false)), _) :: _ ->
|
||||
| ((Comment (_, false) | String (_, false) | Quotation (_, false)), _) :: _ ->
|
||||
(* An unterminated command, string, or quotation. *)
|
||||
None
|
||||
| ((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))
|
||||
|
||||
(* Complete with ";;" when possible. *)
|
||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, { idx2 = stop })]
|
||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String true, _); (Blanks, { idx2 = stop })] ->
|
||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String (_, true), { idx2 = stop })]
|
||||
| [(Symbol "#", _); ((Lident _ | Uident _), _); (String (_, true), _); (Blanks, { idx2 = stop })] ->
|
||||
(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
|
||||
(start, [(phrase_terminator, "")])
|
||||
else
|
||||
(0, [])
|
||||
|
||||
(* Completion on #require. *)
|
||||
| [(Symbol "#", _); (Lident "require", _); (String false, loc)] ->
|
||||
let pkg = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident "require", _); (String (tlen, false), loc)] ->
|
||||
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
|
||||
(loc.idx1 + 1, List.map (fun pkg -> (pkg, "\"" ^ phrase_terminator)) (List.sort compare pkgs))
|
||||
|
||||
| [(Symbol "#", _); (Lident "typeof", _); (String false, loc)] ->
|
||||
let prefix = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident "typeof", _); (String (tlen, false), loc)] ->
|
||||
let prefix = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||
begin match Longident.parse prefix with
|
||||
| Longident.Ldot (lident, last_prefix) ->
|
||||
let set = names_of_module lident in
|
||||
|
@ -877,8 +877,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
|||
end
|
||||
|
||||
(* Completion on #load. *)
|
||||
| [(Symbol "#", _); (Lident ("load" | "load_rec"), _); (String false, loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident ("load" | "load_rec"), _); (String (tlen, false), loc)] ->
|
||||
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 map =
|
||||
if Filename.is_relative file then
|
||||
|
@ -898,8 +898,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
|||
|
||||
#if OCAML_VERSION >= (4, 02, 0)
|
||||
(* Completion on #ppx. *)
|
||||
| [(Symbol "#", _); (Lident ("ppx"), _); (String false, loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident ("ppx"), _); (String (tlen, false), loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||
let filter ~dir_ok name =
|
||||
try
|
||||
Unix.access name [Unix.X_OK];
|
||||
|
@ -928,8 +928,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
|||
#endif
|
||||
|
||||
(* Completion on #use. *)
|
||||
| [(Symbol "#", _); (Lident "use", _); (String false, loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident "use", _); (String (tlen, false), loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||
let filter name =
|
||||
match try Some (String.rindex name '.') with Not_found -> None with
|
||||
| None ->
|
||||
|
@ -955,8 +955,8 @@ let complete ~syntax ~phrase_terminator ~input =
|
|||
List.map (function (w, Directory) -> (w, "") | (w, File) -> (w, "\"" ^ phrase_terminator)) result)
|
||||
|
||||
(* Completion on #directory and #cd. *)
|
||||
| [(Symbol "#", _); (Lident ("cd" | "directory"), _); (String false, loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + 1) (String.length input - loc.ofs1 - 1) in
|
||||
| [(Symbol "#", _); (Lident ("cd" | "directory"), _); (String (tlen, false), loc)] ->
|
||||
let file = String.sub input (loc.ofs1 + tlen) (String.length input - loc.ofs1 - tlen) in
|
||||
let list = list_directories (Filename.dirname file) in
|
||||
let name = basename file 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 idx2, terminated = string (idx + 1) 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' ' ' '\''] "'"
|
||||
|
@ -217,6 +223,18 @@ and string idx = parse
|
|||
| eof
|
||||
{ (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
|
||||
| '<' (':' ident)? ('@' lident)? '<'
|
||||
{ quotation syntax (depth + 1) idx1 (idx2 + lexeme_size lexbuf) ofs1 lexbuf }
|
||||
|
|
|
@ -30,8 +30,8 @@ type t =
|
|||
| Uident of string
|
||||
| Constant of string
|
||||
| Char
|
||||
| String of bool
|
||||
(** [String terminated]. *)
|
||||
| String of int * bool
|
||||
(** [String (quote_size, terminated)]. *)
|
||||
| Comment of comment_kind * bool
|
||||
(** [Comment (kind, terminated)]. *)
|
||||
| Blanks
|
||||
|
|
Loading…
Reference in New Issue