From f58b7ff4147761f6cfa5dae2ef7df080b3c84353 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 8 Sep 2017 17:28:07 +0200 Subject: [PATCH 1/3] REPL: edit_backspace: fix bad passed option --- base/repl/LineEdit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/repl/LineEdit.jl b/base/repl/LineEdit.jl index ebf27b7a7bad9..bcfc57cda6f76 100644 --- a/base/repl/LineEdit.jl +++ b/base/repl/LineEdit.jl @@ -551,7 +551,7 @@ end # on the right function edit_backspace(s::PromptState, align::Bool=false, adjust=align) push_undo(s) - if edit_backspace(buffer(s), align) + if edit_backspace(buffer(s), align, adjust) refresh_line(s) else pop_undo(s) From b9ba7c499be85652b0603eb1d8fdbe7a46dff9b7 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 8 Sep 2017 17:34:42 +0200 Subject: [PATCH 2/3] REPL: add an Options type to handle REPL options It was previously not practical to disable the "align" feature of backspace: overwriting the '\b' binding with: `'\b' => (s,o...) -> Base.LineEdit.edit_backspace(s, false)` worked to a certain extent, but for example it was disabling the feature that '\b' must get you out of shell/help mode. A new experimental Options type is introduced here, which is meant to conveniently allow users to pass options controlling the REPL behavior. For example: atreplinit() do repl repl.options = Base.REPL.Options(backspace_align = false) end --- base/repl/LineEdit.jl | 19 +++++++++++-------- base/repl/REPL.jl | 19 +++++++++++++++---- test/lineedit.jl | 8 ++++---- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/base/repl/LineEdit.jl b/base/repl/LineEdit.jl index bcfc57cda6f76..72cf884858464 100644 --- a/base/repl/LineEdit.jl +++ b/base/repl/LineEdit.jl @@ -27,7 +27,7 @@ mutable struct Prompt <: TextInterface # Same as prefix except after the prompt prompt_suffix::Union{String,Function} keymap_dict::Dict{Char} - keymap_func_data # ::AbstractREPL + repl # ::AbstractREPL complete # ::REPLCompletionProvider on_enter::Function on_done::Function @@ -75,6 +75,8 @@ mutable struct PromptState <: ModeState indent::Int end +options(s::PromptState) = isdefined(s.p, :repl) ? s.p.repl.options : Base.REPL.Options() + setmark(s) = mark(buffer(s)) # the default mark is 0 @@ -116,7 +118,7 @@ terminal(s::PromptState) = s.terminal for f in [:terminal, :on_enter, :add_history, :buffer, :(Base.isempty), :replace_line, :refresh_multi_line, :input_string, :update_display_buffer, - :empty_undo, :push_undo, :pop_undo] + :empty_undo, :push_undo, :pop_undo, :options] @eval ($f)(s::MIState, args...) = $(f)(state(s), args...) end @@ -549,7 +551,8 @@ end # align: delete up to 4 spaces to align to a multiple of 4 chars # adjust: also delete spaces on the right of the cursor to try to keep aligned what is # on the right -function edit_backspace(s::PromptState, align::Bool=false, adjust=align) +function edit_backspace(s::PromptState, align::Bool=options(s).backspace_align, + adjust=options(s).backspace_adjust) push_undo(s) if edit_backspace(buffer(s), align, adjust) refresh_line(s) @@ -571,7 +574,7 @@ function endofline(buf, pos=position(buf)) eol == 0 ? buf.size : pos + eol - 1 end -function edit_backspace(buf::IOBuffer, align::Bool=false, adjust::Bool=align) +function edit_backspace(buf::IOBuffer, align::Bool=false, adjust::Bool=false) !align && adjust && throw(DomainError((align, adjust), "if `adjust` is `true`, `align` must be `true`")) @@ -1649,7 +1652,7 @@ AnyDict( end, '\n' => KeyAlias('\r'), # Backspace/^H - '\b' => (s,o...)->edit_backspace(s, true), + '\b' => (s,o...)->edit_backspace(s), 127 => KeyAlias('\b'), # Meta Backspace "\e\b" => (s,o...)->edit_delete_prev_word(s), @@ -1860,14 +1863,14 @@ function Prompt(prompt; prompt_prefix = "", prompt_suffix = "", keymap_dict = default_keymap_dict, - keymap_func_data = nothing, + repl = nothing, complete = EmptyCompletionProvider(), on_enter = default_enter_cb, on_done = ()->nothing, hist = EmptyHistoryProvider(), sticky = false) - Prompt(prompt, prompt_prefix, prompt_suffix, keymap_dict, keymap_func_data, + Prompt(prompt, prompt_prefix, prompt_suffix, keymap_dict, repl, complete, on_enter, on_done, hist, sticky) end @@ -1968,7 +1971,7 @@ end edit_redo!(s) = nothing keymap(s::PromptState, prompt::Prompt) = prompt.keymap_dict -keymap_data(s::PromptState, prompt::Prompt) = prompt.keymap_func_data +keymap_data(s::PromptState, prompt::Prompt) = prompt.repl keymap(ms::MIState, m::ModalInterface) = keymap(state(ms), mode(ms)) keymap_data(ms::MIState, m::ModalInterface) = keymap_data(state(ms), mode(ms)) diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index c8fc5a3fb42ba..c975b1b6329f5 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -241,6 +241,16 @@ function run_frontend(repl::BasicREPL, backend::REPLBackendRef) dopushdisplay && popdisplay(d) end +## Custom Options + +mutable struct Options + backspace_align::Bool + backspace_adjust::Bool +end + +Options(; backspace_align=true, backspace_adjust=backspace_align) = + Options(backspace_align, backspace_adjust) + ## LineEditREPL ## mutable struct LineEditREPL <: AbstractREPL @@ -257,11 +267,12 @@ mutable struct LineEditREPL <: AbstractREPL envcolors::Bool waserror::Bool specialdisplay::Union{Void,Display} + options::Options interface::ModalInterface backendref::REPLBackendRef LineEditREPL(t,hascolor,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell,in_help,envcolors) = new(t,true,prompt_color,input_color,answer_color,shell_color,help_color,history_file,in_shell, - in_help,envcolors,false,nothing) + in_help,envcolors,false,nothing, Options()) end outstream(r::LineEditREPL) = r.t specialdisplay(r::LineEditREPL) = r.specialdisplay @@ -741,7 +752,7 @@ function setup_interface( prompt_prefix = hascolor ? repl.prompt_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", - keymap_func_data = repl, + repl = repl, complete = replc, on_enter = return_callback) @@ -750,7 +761,7 @@ function setup_interface( prompt_prefix = hascolor ? repl.help_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", - keymap_func_data = repl, + repl = repl, complete = replc, # When we're done transform the entered line into a call to help("$line") on_done = respond(Docs.helpmode, repl, julia_prompt)) @@ -760,7 +771,7 @@ function setup_interface( prompt_prefix = hascolor ? repl.shell_color : "", prompt_suffix = hascolor ? (repl.envcolors ? Base.input_color : repl.input_color) : "", - keymap_func_data = repl, + repl = repl, complete = ShellCompletionProvider(), # Transform "foo bar baz" into `foo bar baz` (shell quoting) # and pass into Base.repl_cmd for processing (handles `ls` and `cd` diff --git a/test/lineedit.jl b/test/lineedit.jl index db08ac64c2bc4..ac03ee24229b5 100644 --- a/test/lineedit.jl +++ b/test/lineedit.jl @@ -330,7 +330,7 @@ let buf = IOBuffer() @test position(buf) == 0 LineEdit.edit_move_right(buf) @test nb_available(buf) == 0 - LineEdit.edit_backspace(buf) + LineEdit.edit_backspace(buf, false, false) @test content(buf) == "a" end @@ -699,9 +699,9 @@ end @test edit!(edit_undo!) == "one two three" LineEdit.move_line_end(s) - LineEdit.edit_backspace(s) - LineEdit.edit_backspace(s) - @test edit!(LineEdit.edit_backspace) == "one two th" + LineEdit.edit_backspace(s, false, false) + LineEdit.edit_backspace(s, false, false) + @test edit!(s->LineEdit.edit_backspace(s, false, false)) == "one two th" @test edit!(edit_undo!) == "one two thr" @test edit!(edit_undo!) == "one two thre" @test edit!(edit_undo!) == "one two three" From 0245e2e49e88a33c324e6458a4c196edf9c1cb17 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 8 Sep 2017 18:22:09 +0200 Subject: [PATCH 3/3] REPL: add hascolor & extra_repl_keymap to Options --- base/repl/REPL.jl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index c975b1b6329f5..d13faef285281 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -241,15 +241,20 @@ function run_frontend(repl::BasicREPL, backend::REPLBackendRef) dopushdisplay && popdisplay(d) end -## Custom Options +## User Options mutable struct Options + hascolor::Bool + extra_keymap::Union{Dict,Vector{<:Dict}} backspace_align::Bool backspace_adjust::Bool end -Options(; backspace_align=true, backspace_adjust=backspace_align) = - Options(backspace_align, backspace_adjust) +Options(; + hascolor = true, + extra_keymap = AnyDict[], + backspace_align = true, backspace_adjust = backspace_align) = + Options(hascolor, extra_keymap, backspace_align, backspace_adjust) ## LineEditREPL ## @@ -714,8 +719,9 @@ enable_promptpaste(v::Bool) = JL_PROMPT_PASTE[] = v function setup_interface( repl::LineEditREPL; - hascolor::Bool = repl.hascolor, - extra_repl_keymap::Union{Dict,Vector{<:Dict}} = Dict{Any,Any}[] + # those keyword arguments may be deprecated eventually in favor of the Options mechanism + hascolor::Bool = repl.options.hascolor, + extra_repl_keymap::Union{Dict,Vector{<:Dict}} = repl.options.extra_keymap ) ### #