Skip to content

Commit

Permalink
All local variables can be minified
Browse files Browse the repository at this point in the history
  • Loading branch information
gridbugs committed Oct 25, 2024
1 parent d5e44af commit a457f52
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 49 deletions.
103 changes: 64 additions & 39 deletions src/climate/completion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,15 @@ module Reentrant_query = struct
command
(Value.literal_with_local_variable query_index ~f:(fun query_index ->
sprintf
"%s %s=%s -- $COMP_LINE"
"%s %s=$%s -- $COMP_LINE"
program_exe
(Name.to_string_with_dashes print_reentrant_completions_name)
query_index))
]
; raw_with_local_variable2
command
current_word
~f:(sprintf "COMPREPLY+=($(compgen -W \"$(eval \"%s\")\" -- \"%s\"))")
~f:(sprintf "COMPREPLY+=($(compgen -W \"$(eval \"$%s\")\" -- \"$%s\"))")
]
;;
end
Expand Down Expand Up @@ -241,6 +241,12 @@ module Subcommand_and_positional_arg_completion = struct
~command_hash_in_function_names
=
let open Stmt in
let prev_word_was_named_argument_with_value =
Local_variable.create "prev_word_was_named_argumen_with_value" ~short_name:"p"
in
let positional_argument_index =
Local_variable.create "positional_argument_index" ~short_name:"i"
in
let base_function_name =
function_name ~subcommand_path ~command_hash_in_function_names
in
Expand Down Expand Up @@ -335,7 +341,10 @@ module Subcommand_and_positional_arg_completion = struct
|> Nonempty_list.of_list
|> Option.map ~f:(fun patterns ->
( Case_pattern.union patterns
, [ raw "prev_word_was_named_argument_with_value=1" ] ))
, [ raw_with_local_variable
prev_word_was_named_argument_with_value
~f:(sprintf "%s=1")
] ))
|> Option.to_list
in
let subcommands =
Expand All @@ -360,22 +369,32 @@ module Subcommand_and_positional_arg_completion = struct
@ subcommands
@ [ ( Case_pattern.singleton "-*"
, [ comment "Ignore other words that look like arguments"
; raw "prev_word_was_named_argument_with_value=0"
; raw_with_local_variable
prev_word_was_named_argument_with_value
~f:(sprintf "%s=0")
] )
; ( Case_pattern.singleton "*"
, [ if_
(Cond.test_raw
"\"$prev_word_was_named_argument_with_value\" -eq 0")
[ raw "positional_argument_index=$((positional_argument_index+1))"
(Cond.test_raw_of_string_with_local_variable
prev_word_was_named_argument_with_value
~f:(sprintf "\"$%s\" -eq 0"))
[ raw_with_local_variable2
positional_argument_index
positional_argument_index
~f:(sprintf "%s=$((%s+1))")
]
; raw "prev_word_was_named_argument_with_value=0"
; raw_with_local_variable
prev_word_was_named_argument_with_value
~f:(sprintf "%s=0")
] )
]
in
function_
base_function_name
[ raw "local prev_word_was_named_argument_with_value=0"
; raw "local positional_argument_index=0"
[ declare_local_variables
[ local_init prev_word_was_named_argument_with_value (Value.literal "0")
; local_init positional_argument_index (Value.literal "0")
]
; while_
Cond.true_
[ if_
Expand Down Expand Up @@ -408,7 +427,7 @@ module Subcommand_and_positional_arg_completion = struct
call
complete_positional_args_function
[ Value.argument 2
; Value.literal "$positional_argument_index"
; Value.local_variable positional_argument_index
]
| None ->
comment
Expand Down Expand Up @@ -436,34 +455,40 @@ module Subcommand_and_positional_arg_completion = struct
; return (Value.global Status.done_)
]
~else_:
[ comment
"Avoid the variable name \"status\" as it's reserved by some \
shells."
; raw "local current_word status_"
; raw_with_global_name
~f:(sprintf "current_word=$(%s)")
(name Comp_words.Traverse.get_current)
; raw "status_=$?"
; if_
(Cond.test_raw "\"$status_\" -ne 0")
[ return (Value.literal "$status_") ]
; call Comp_words.Traverse.advance []
; if_
(Cond.call Comp_words.Traverse.is_past_cursor [])
[ comment
"Bounds check to catch errors in the implementation of \
the completion script"
; return (Value.global Status.error_word_index_past_cursor)
]
; if_
(Cond.call Comp_words.Traverse.is_at_cursor [])
[ comment
"The parser has reached the word under the cursor. \
Attempt to complete it and then exit."
; case (Value.literal "$current_word") named_arg_cases
]
; case (Value.literal "$current_word") subcommand_cases
]
(let current_word =
Local_variable.create "current_word" ~short_name:"w"
in
(* Avoid the variable name "status" as it's reserved by some shells. *)
let status = Local_variable.create "status_" ~short_name:"s" in
[ declare_local_variables
[ local_decl current_word; local_decl status ]
; raw_with_local_variable_and_global_name
current_word
(name Comp_words.Traverse.get_current)
~f:(sprintf "%s=$(%s)")
; raw_with_local_variable status ~f:(sprintf "%s=$?")
; if_
(Cond.test_raw_of_string_with_local_variable
status
~f:(sprintf "\"$%s\" -ne 0"))
[ return (Value.local_variable status) ]
; call Comp_words.Traverse.advance []
; if_
(Cond.call Comp_words.Traverse.is_past_cursor [])
[ comment
"Bounds check to catch errors in the implementation of \
the completion script"
; return (Value.global Status.error_word_index_past_cursor)
]
; if_
(Cond.call Comp_words.Traverse.is_at_cursor [])
[ comment
"The parser has reached the word under the cursor. \
Attempt to complete it and then exit."
; case (Value.local_variable current_word) named_arg_cases
]
; case (Value.local_variable current_word) subcommand_cases
])
]
])
]
Expand Down
46 changes: 36 additions & 10 deletions src/climate/shell_dsl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ and cond =
| Call of function_call
| Test_raw_cond of string
| Test_raw_cond_of_string_with_global_name of string_with_global_name
| Test_raw_cond_of_string_with_local_variable of (Local_variable.t * (string -> string))

and conditional_block =
{ cond : cond
Expand Down Expand Up @@ -93,6 +94,8 @@ and stmt =
| Raw_with_local_variable of (Local_variable.t * (string -> string))
| Raw_with_local_variable2 of
(Local_variable.t * Local_variable.t * (string -> string -> string))
| Raw_with_local_variable_and_global_name of
(Local_variable.t * global_name * (string -> string -> string))

module Global_name = struct
type t = global_name
Expand Down Expand Up @@ -168,6 +171,10 @@ module Cond = struct
Test_raw_cond_of_string_with_global_name { string_of_name = f; global_name }
;;

let test_raw_of_string_with_local_variable ~f v =
Test_raw_cond_of_string_with_local_variable (v, f)
;;

let map_global_name_suffix t ~f =
match t with
| Call { function_; args } ->
Expand Down Expand Up @@ -218,6 +225,11 @@ module Stmt = struct
let declare_local_variables vars = Declare_local_variables vars
let raw_with_local_variable var ~f = Raw_with_local_variable (var, f)
let raw_with_local_variable2 var0 var1 ~f = Raw_with_local_variable2 (var0, var1, f)

let raw_with_local_variable_and_global_name local_variable global_name ~f =
Raw_with_local_variable_and_global_name (local_variable, global_name, f)
;;

let comment s = Comment s
let noop = Noop

Expand All @@ -233,6 +245,9 @@ module Stmt = struct
| Raw_with_global_name { string_of_name; global_name } ->
Raw_with_global_name
{ string_of_name; global_name = Global_name.with_suffix global_name ~f }
| Raw_with_local_variable_and_global_name (local_variable, global_name, g) ->
Raw_with_local_variable_and_global_name
(local_variable, Global_name.with_suffix global_name ~f, g)
| Cond cond -> Cond (Cond.map_global_name_suffix cond ~f)
| If { if_ = { cond; body }; elifs; else_ } ->
let cond = Cond.map_global_name_suffix cond ~f in
Expand Down Expand Up @@ -268,6 +283,7 @@ module Stmt = struct
match t with
| Raw _
| Raw_with_global_name _
| Raw_with_local_variable_and_global_name _
| Cond _
| Return _
| Comment _
Expand Down Expand Up @@ -339,7 +355,7 @@ module Bash = struct
| Argument index -> sprintf "\"$%d\"" index
| Literal_with_local_variable (v, f) ->
let variable_string =
sprintf "$%s" (Local_variable.to_string ~style:ctx.local_variable_style v)
sprintf "%s" (Local_variable.to_string ~style:ctx.local_variable_style v)
in
sprintf "\"%s\"" (f variable_string)

Expand All @@ -364,6 +380,9 @@ module Bash = struct
string_with_global_name
in
sprintf "[ %s ]" s
| Test_raw_cond_of_string_with_local_variable (v, f) ->
let s = Local_variable.to_string ~style:ctx.local_variable_style v in
sprintf "[ %s ]" (f s)
;;

type line =
Expand Down Expand Up @@ -397,6 +416,19 @@ module Bash = struct
string_with_global_name
in
[ { text; indent } ]
| Raw_with_local_variable_and_global_name (local_variable, global_name, f) ->
let text =
let global_name_string =
Global_name.with_prefix
~global_symbol_prefix:ctx.global_symbol_prefix
global_name
in
let local_variable_string =
Local_variable.to_string ~style:ctx.local_variable_style local_variable
in
f local_variable_string global_name_string
in
[ { indent; text } ]
| Cond c ->
let text = cond_to_string ~ctx c in
[ { text; indent } ]
Expand Down Expand Up @@ -455,17 +487,11 @@ module Bash = struct
}
]
| Raw_with_local_variable (var, f) ->
let var_string =
sprintf "$%s" (Local_variable.to_string ~style:ctx.local_variable_style var)
in
let var_string = Local_variable.to_string ~style:ctx.local_variable_style var in
[ { indent; text = f var_string } ]
| Raw_with_local_variable2 (var0, var1, f) ->
let var0_string =
sprintf "$%s" (Local_variable.to_string ~style:ctx.local_variable_style var0)
in
let var1_string =
sprintf "$%s" (Local_variable.to_string ~style:ctx.local_variable_style var1)
in
let var0_string = Local_variable.to_string ~style:ctx.local_variable_style var0 in
let var1_string = Local_variable.to_string ~style:ctx.local_variable_style var1 in
[ { indent; text = f var0_string var1_string } ]
in
loop indent
Expand Down
18 changes: 18 additions & 0 deletions src/climate/shell_dsl.mli
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module Value : sig
(** A positional argument to the current function or program *)
val argument : int -> t

(** Calls [f] on the name of the local variable without the leading "$" *)
val literal_with_local_variable : Local_variable.t -> f:(string -> string) -> t
end

Expand All @@ -67,6 +68,12 @@ module Cond : sig
val call : Global_named_value.t -> Value.t list -> t
val test_raw : string -> t
val test_raw_of_string_with_global_name : f:(string -> string) -> Global_name.t -> t

(** Call [f] on the name of the local variable without the leading "$" *)
val test_raw_of_string_with_local_variable
: f:(string -> string)
-> Local_variable.t
-> t
end

module Case_pattern : sig
Expand Down Expand Up @@ -103,14 +110,25 @@ module Stmt : sig
val local_decl : Local_variable.t -> local_variable_decl
val local_init : Local_variable.t -> Value.t -> local_variable_decl
val declare_local_variables : local_variable_decl list -> t

(** Calls [f] on the name of the local variable _without_ the leading "$" so
the variable can be assigned to. *)
val raw_with_local_variable : Local_variable.t -> f:(string -> string) -> t

(** Calls [f] on the name of the local variables _without_ the leading "$" so
the variables can be assigned to. *)
val raw_with_local_variable2
: Local_variable.t
-> Local_variable.t
-> f:(string -> string -> string)
-> t

val raw_with_local_variable_and_global_name
: Local_variable.t
-> Global_name.t
-> f:(string -> string -> string)
-> t

(** Call a given function on all blocks appearing within the statement. *)
val transform_blocks_top_down : t list -> f:(t list -> t list) -> t list

Expand Down

0 comments on commit a457f52

Please sign in to comment.