masonprotter / replmaker.jl Goto Github PK
View Code? Open in Web Editor NEWSimple API for building repl modes in Julia
License: Other
Simple API for building repl modes in Julia
License: Other
the suggested method is to add
atreplinit() do repl
try
@eval using ReplMaker
@async initrepl(
apropos;
prompt_text="search> ",
prompt_color=:magenta,
start_key=')',
mode_name="search_mode"
)
catch
end
end
now if we look at line 393 in client.jl we see
373 function run_main_repl(interacti
...
...
393 │ │ │ _atreplinit(active_repl)
394 │ │ │ REPL.run_repl(active_repl, backend->(global active_repl_backend = backend))
_atreplinit
gets called before REPL.run_repl ,
now there are lines inside initrepl
like .. julia_mode = active_repl.interface.modes[1]
will only work after
REPL.run_repl has run (right?) .
My question is .. how is @async making this happen ?
is this a "hack" such that run_repl is able to setup_interface
and all other initializations that initrepl needs before @async initrepl
is accessing them , what if the async reaches something(for eg line 68 julia_mode = ...
) that has not been initialized by REPL.run yet ?
(Reduce.jl traced this issue to ReplMaker.jl)
julia> using Reduce
[ Info: Precompiling Reduce [93e0c654-6965-5f22-aba9-9c1ae6b3c259]
ERROR: InitError: MethodError: no method matching keymap(::Vector{Dict})
Closest candidates are:
keymap(::Any, ::Union{REPL.LineEdit.HistoryPrompt, REPL.LineEdit.PrefixHistoryPrompt}) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\LineEdit.jl:2007
keymap(::Union{Vector{Dict{Any, Any}}, Vector{Dict{Char, Any}}}) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\LineEdit.jl:1610
keymap(::REPL.LineEdit.PromptState, ::REPL.LineEdit.Prompt) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\REPL\src\LineEdit.jl:2505
...
Stacktrace:
[1] initrepl(parser::typeof(Reduce.parserepl); prompt_text::String, prompt_color::Symbol, start_key::Char, repl::REPL.LineEditREPL, mode_name::String, valid_input_checker::Function, keymap::Dict{Char, Any}, completion_provider::REPL.REPLCompletionProvider, sticky_mode::Bool, startup_text::Bool)
@ ReplMaker ~.julia\packages\ReplMaker\pwo5w\src\ReplMaker.jl:78
[2] repl_init(repl::REPL.LineEditREPL)
@ Reduce ~.julia\packages\Reduce\1n3pM\src\repl.jl:45
[3] repl_init
@ ~.julia\packages\Reduce\1n3pM\src\repl.jl:60 [inlined]
[4] init()
@ Reduce ~.julia\packages\Reduce\1n3pM\src\Reduce.jl:322
[5] _include_from_serialized(path::String, depmods::Vector{Any})
@ Base .\loading.jl:597
[6] _require_from_serialized(path::String, cache::Base.TOMLCache)
@ Base .\loading.jl:649
[7] _require(pkg::Base.PkgId, cache::Base.TOMLCache)
@ Base .\loading.jl:952
[8] require(uuidkey::Base.PkgId, cache::Base.TOMLCache)
@ Base .\loading.jl:836
[9] require(into::Module, mod::Symbol)
@ Base .\loading.jl:824
during initialization of module Reduce
julia> versioninfo()
Julia Version 1.6.0-DEV.913
Commit 4c805d2310 (2020-09-14 14:07 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Xeon(R) E-2176M CPU @ 2.70GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
JULIA_NUM_THREADS = 8
Feel free to close this issue, and I totally get that people opening such issues is usually very annoying. In any case, thought I'd mention the following packages
REPLHistory REPLTreeViews REPLCompletions REPLTetris
and the REPL
stdlib, which makes me wonder if it would be a good idea to alias the package name to REPLMaker
Sometimes I want to give a user the opportunity to intervene in some otherwise-automated process if a certain condition is satisfied.
As a toy example, consider an AbstractDict
object where upon inserting a key-value, if the key exists and isinteractive()
, the user is dropped into a REPL mode that lets them inspect the contents of the dictionary, the pair being added, and decide what to do.
Currently I don't think ReplMaker
can be used for this case, because it can only add REPL modes which are triggered from a key-press in the default Julia REPL. What would be needed is something that returns a REPL object and runs it on call. I don't think this would require too much on top of the REPL
stdlib, however the stdlib does not have a very good (or well documented) API for this sort of thing, so I think it would be worth doing here.
Is there an API to start it by force? once I invoke initrepl
?
Upon:
initrepl(LispSyntax.lisp_eval_helper,
valid_input_checker=valid_sexpr,
prompt_text="λ> ",
prompt_color=:red,
start_key=")",
mode_name="Lisp Mode")
I get:
ERROR: MethodError: no method matching setup_interface(::REPL.BasicREPL)
Closest candidates are:
setup_interface(!Matched::REPL.LineEditREPL; hascolor, extra_repl_keymap) at /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/st
dlib/v1.8/REPL/src/REPL.jl:908
setup_interface(!Matched::REPL.LineEditREPL, !Matched::Bool, !Matched::Any) at /Applications/Julia-1.8.app/Contents/Resources/julia/share/julia/
stdlib/v1.8/REPL/src/REPL.jl:911
Stacktrace:
[1] initrepl(parser::typeof(LispSyntax.lisp_eval_helper); prompt_text::String, prompt_color::Symbol, start_key::String, repl::REPL.BasicREPL, mod
e_name::String, show_function::Nothing, show_function_io::Base.TTY, valid_input_checker::Function, keymap::Dict{Char, Any}, completion_provider::R
EPL.REPLCompletionProvider, sticky_mode::Bool, startup_text::Bool)
@ ReplMaker ~/.julia/packages/ReplMaker/ViCwA/src/ReplMaker.jl:64
[2] top-level scope
@ none:1
An error appears when trying to overwrite the shell model key with julia 1.8
.
julia> using ReplMaker
julia> function parse_to_expr(s)
quote Meta.parse($s) end
end
parse_to_expr (generic function with 1 method)
julia> initrepl(parse_to_expr,
prompt_text="Expr> ",
prompt_color = :blue,
start_key=';',
mode_name="Expr_mode")
┌ Warning: REPL key ';' overwritten.
└ @ ReplMaker C:\Users\ilyao\.julia\packages\ReplMaker\ViCwA\src\ReplMaker.jl:96
ERROR: MethodError: no method matching deepcopy_internal(::Base.Threads.SpinLock)
Closest candidates are:
deepcopy_internal(::Base.AbstractLock, ::IdDict) at deepcopy.jl:130
deepcopy_internal(::Any, ::IdDict) at deepcopy.jl:53
deepcopy_internal(::BigInt, ::IdDict) at gmp.jl:794
...
Stacktrace:
[1] deepcopy_internal(x::Base.GenericCondition{Base.Threads.SpinLock}, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:143
[2] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any}) (repeats 4 times)
@ Base .\deepcopy.jl:65
[3] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:76
[4] deepcopy_internal(x::Dict{Char, Any}, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:125
[5] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:65
[6] deepcopy_internal(x::Dict{Symbol, REPL.LineEdit.Prompt}, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:125
[7] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any}) (repeats 2 times)
@ Base .\deepcopy.jl:65
[8] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:76
[9] deepcopy_internal(x::Dict{Char, Any}, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:125
[10] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:65
[11] deepcopy_internal(x::Any, stackdict::IdDict{Any, Any})
@ Base .\deepcopy.jl:76
[12] deepcopy(x::Function)
@ Base .\deepcopy.jl:26
[13] initrepl(parser::typeof(parse_to_expr); prompt_text::String, prompt_color::Symbol, start_key::Char, repl::REPL.LineEditREPL, mode_name::String, show_function::Nothing, show_function_io::Base.TTY, valid_input_checker::Function, keymap::Dict{Char, Any}, completion_provider::REPL.REPLCompletionProvider, sticky_mode::Bool, startup_text::Bool)
@ ReplMaker C:\Users\ilyao\.julia\packages\ReplMaker\ViCwA\src\ReplMaker.jl:97
[14] top-level scope
@ REPL[3]:1
It'd be good if the user could supply a custom function other than show
, or thier own IO / MIME type to be used when show
is called in a custom REPL mode.
OhMyREPL
is a package that enhances the base Julia REPL, in part by making various keys do useful things, like making {
insert a closing curly bracket (and making it such that when one presses }
while in front of to the }
character, it moves over the latter and inserts nothing). To do so, it rebinds various keys, many of which are used (by other packages) to enter REPLs (for example, }
is used by Reduce.jl). If ReplMaker
detects that a key is in use by another package, it spits out a warning and does nothing else, causing the former keybind to break.
Note: a Unicode combining underscore (U+0332
, ̲) follows the current cursor position in these examples.
julia> using OhMyREPL, ReplMaker
[ Info: Precompiling OhMyREPL [5fb14364-9ced-5910-84b2-373655c76a03]
[ Info: Precompiling ReplMaker [b873ce64-0db9-51f5-a568-4457d8e49576]
julia> ̲
Press {
:
julia> { ̲}
Press }
:
julia> {} ̲
Throw another keybind in:
julia> initrepl(identity, start_key='}')
┌ Warning: REPL key '}' overwritten.
└ @ ReplMaker ~/.julia/packages/ReplMaker/SZ5Aa/src/ReplMaker.jl:96
REPL mode mylang initialized. Press } to enter and backspace to exit.
"Prompt(\"myrepl> \",...)"
(The REPL mode works)
Mess with braces again
Press {
:
julia> { ̲}
Press }
:
julia> {} ̲}
julia> using OhMyREPL, ReplMaker
[ Info: Precompiling OhMyREPL [5fb14364-9ced-5910-84b2-373655c76a03]
[ Info: Precompiling ReplMaker [b873ce64-0db9-51f5-a568-4457d8e49576]
julia> initrepl(identity, start_key='}')
┌ Warning: REPL key '}' overwritten.
└ @ ReplMaker ~/.julia/packages/ReplMaker/SZ5Aa/src/ReplMaker.jl:96
REPL mode mylang initialized. Press } to enter and backspace to exit.
"Prompt(\"myrepl> \",...)"
julia>
Mess with braces again
Press {
:
julia> { ̲}
Press }
:
julia> {} ̲
(The REPL mode still works, but the keybind is triggered)
The initrepl
function accepts a completion_provider
keyword which, by default, provides the Julia REPL auto completion feature.
Which value should I pass to completion_provider
to disable auto completion for a custom repl?
Is there a way to remove or disable a REPL mode once installed with initrepl()
?
For example, I'm trying to import a package which initiates its own REPL mode via ReplMaker.jl that I don't want to expose through my package.
I think that having fun the package default to binding a repl mode to a key is probably a bad idea.
One idea that may be preferable is if the package hid all new repl modes behind a menu so one has to press one key to bring up a menu of modes and then another key to select which mode they want.
Another possibility is requiring that the key be accompanied by a modifier key. Ie. one must press alt+}
to open the repl mode.
I’m definitely open to suggestions and PRs here. I don’t know how to implement that first idea but the second one is doable.
Lets say I want everything in the REPL to modify a variable x
.
I would like to do
mutable struct X
a
end
x = X(0)
@mod x # enter repl maker
mod> add!(2) # x.a = x.a +1,
How would I accomplish this in ReplMaker? Reading through the source code, it's not obvious.
I would like to have the Ctrl-Q (https://docs.julialang.org/en/v1/stdlib/REPL/#Key-bindings) functionality implemented for my custom REPL mode, with custom behaviour.
Is this at all possible?
I haven't tried on older julias, but at least 1.9 I can't get it to work. I had someone else test it on a different OS and confirmed.
Is this related to a Base issue?
Thanks
I would like to suggest being able to invoke a REPL, with a shortcut combo, instead of just one key, give Julia expressiveness it seems only )
and }
are available >
is legal:
julia> )
ERROR: syntax: unexpected ")"
Stacktrace:
[1] top-level scope
@ none:1
julia> }
ERROR: syntax: unexpected "}"
Stacktrace:
[1] top-level scope
@ none:1
julia> >
> (generic function with 3 methods)
The current setup only allows for a couple of "non-legal" julia AKA, available for one key REPL command. I have become addicted to creating REPLs but there is no way to have multiple open, without taking away legal characters from Julia.
Best regards.
I'd like to launch a background task to send commands from my custom repl-mode to. Launching that process takes a few hundred ms, and I'd like to do it asynchronously when a user enters the repl mode so it's ready by the time they send commands.
I may missing it, but is there straight-forward way of overwriting the current REPL instance by changing the prompt_text or mode_name? Looking for something similar to the Pkg REPL mode where the name changes after you activate an environment.
Sorry for the spam.
It looks like REPL modes give raw strings to the input function. I'm making a ChatGPT REPL mode https://github.com/anandijain/OpenAIReplMode.jl and I think it would be really nice to be able to say
julia> x = "world"
chatgpt> hello $x
and have the string somehow get reinterpolated/unescaped?
Any recommendations for this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.