I wanted to dig into the sourcecode of the shell helper functions, and I cannot find some of the implementations, for example e(N), v(N), f(X).
I would appreciate a pointer to their whereabouts!
I wanted to dig into the sourcecode of the shell helper functions, and I cannot find some of the implementations, for example e(N), v(N), f(X).
I would appreciate a pointer to their whereabouts!
They are implemented here: otp/shell.erl at 0a114f4d06e8c7634722c27788cbf9c13d8fd857 ¡ erlang/otp ¡ GitHub
Per-project history is possible with a combination of direnv with ERL_FLAGS
and -kernel shell_history_path ...
(already mentioned by @garazdawi). Itâs also language agnostic, so Erlang and Elixir can have their respective separate histories.
Thank you!
I have reconsidered my use case.
Usually it is like this:
So, normally I have the function where I need the doc already in the history.
I wrote the new shell command hh(N), which takes an expression from the shell history,
walks down its abstract format tree and calls h(M,F) for every function call.
I have not found functions to deal with AF, so I wrote my own tree walker.
The implementation is here:
Test functions for ct are still missing.
If you are interested, I could make a PR out of it.
Otherwise if anybody is interested it should be possible to implement it via user_default.
Example:
5> element([1,2,3], 4).
** exception error: bad argument
in function element/2
called as element([1,2,3],4)
*** argument 1: not an integer
*** argument 2: not a tuple
6> hh(-1).
-spec element(N, Tuple) -> term()
when N :: pos_integer(), Tuple :: tuple().
Returns the Nth element (numbering from 1) of Tuple, for example:
> element(2, {a, b, c}).
b
Allowed in guard tests.
ok
Great idea.
We were thinking of adding a keyboard shortcut for printing the documentation for the function at the cursor in the current prompt.
1> lists:<Key>
lists doc...
1> lists:seq<Key>
lists:seq doc
1> lists:seq(calendar:localtime<Key>
calendar:localtime doc
1> lists:seq(<Key>calendar:localtime
lists:seq doc again
Tabbing for autocompletion and documentation would compete for the same space after the prompt. So that it will not clutter the shell if you press or multiple times.
I come again with the history subject as I re worked a bit on this subject in a custom :ssh
shell.
A good capacity in the IO/Protocol of erlang would be to overwrite the history behavior. For instance to allow to disable the history for a certain time (for instance when you do hot loads), or even not put in history the command typed in a :io.get_line
.
There is 2 solutions that comes to my mind:
If we consider the shell behavior should be part of the IO protocol. Then may be the solution would be to create a new :io_request
and function that proceed these messages in the :io
module. (The request could be push into history. Pop into history. Or an option like the autocomplete one)
Or we can consider that the shell protcol is an additionnal layer after the IO protocol. We can add a way to pass the control sequence to the processes. (Re reading your previous replies. I think this could be the direction you want to take)
Hello!
Wanted to provide a bit of a summary of what has been done so far.
werl.exe
is now only a link to erl.exe
.erl -remsh
now works in dumb terminals aka âoldshellâ and gives better error indications.shell:start_interactive/1
is it possible to start the interactive shell after Erlang has started, for example from an escript or when starting Erlang using -noshell
.-record(state, {a,b,c})
.foo() -> bar.
.-spec foo() -> atom().
.rr(Module)
"/home/lukas/<TAB>
will now show autocompletion for all files in my $HOME
.-spec
and -type
attributes. This works for both functions in modules and those defined in the shell.Ctrl+O
to open an external $EDITOR to edit the current line.The following bugs have also been fixed:
Soon ⢠we will also have:
We also attempted to:
But they turned out to be far more work than we had expected, so weâll have to tackle them later.
It would be great if you all could try it out and let us know either in this thread or on our issue tracker if you encounter any bugs or idiosyncrasies.
How about the ability to paste a large list or map etc in the shell and not have to up arrow through each line of whatever you pasted?
It was part of our âAdd multiline shell historyâ attempt that failed as it turned out to be more complex than one would think. The problem is not when pasting terms, but rather when pasting code with comments.
We will make better support for it, but we wanted to merge what we had right and take some time to think about how exactly we want to go about it before continuing.
Any chance for enabling the use of parse transforms in the shell via config?
I implemented, as my first elixir project, my own history. One thing I found useful is the ability to save variable bindings between sessions.
One of my everyday pain points is the narrow printing of terms in the shell (normal results, and rp()
). Despite my normal terminal being around 140 columns the terms still print in less than 80 (60 it seems from looking at the code!).
Looks like it would be quick to change, the pp
function (otp/shell.erl at maint ¡ erlang/otp ¡ GitHub) already does lookup the number of columns available, but then hard-code {line_max_chars, ?CHAR_MAX}
(where CHAR_MAX
is defined to be 60).
There are different options, maybe just make it {line_max_chars, colums() - <new constant ~20>}
would perhaps be the natural - but one could think of adding a config option, etcâŚ
For me it would be definitely the multiline editing and history.
Another issue I am facing is that I am unable to cancel the currently typed expression. This happens usually when I am pasting multiline expression that is incorrectly quoted or has unbalanced brackets. I then randomly put periods, quotes, closing brackets to get at least syntax error and free prompt.
Third thing I would like to see is âunoverwritable promptâ. In other words I do not want my prompt to be overwritten when I am in the middle of typing an expression, for example by log output.
For example when following code is running:
F = fun F1() -> logger:error("logged: ~p", [something]), timer:sleep(3000), F1() end.
spawn(fun() -> F() end).
and I am typing longer than 3 seconds, my prompt is overwritten and I am on new line, unable to see where I am, especially when I need to backspace.
Oh yeahhh this would be great. Also there are a whole class of things kinda-like this where it freaks out in the middle of a line, arrowing up through history leaves âghostâ chars at the end, that sort of thing. I always assumed that was just readline or terminal fudgery issues that couldnât really be avoided, am I off track there?
@garazdawi this is wonderful, and all these changes are so much better beyond what I could imagine is possible in such a short period of time.
quickly though (at least for me) thereâs no URL associated with the link to our issue tracker
. maybe thatâs some security issue with Discourse, or maybe something simply didnât get properly attached in your post.
besides tagging along with some of the issues others here have raised (particularly syntax-highlighting the returned values in the shell and the the mangling of the input line in the shell in certain circumstances, such as when interacting with more complicated Unicode sequences), I wonder if one idea could cover a number of wants: a status line as emacs, VIM, BASH, and other shells have.
something like what powerline provides could give people a lot of flexibility in customizing their shell and in communicating information back to the user:
Iâm guessing that would also require a lot of work, but hey, while weâre all making our wishlistsâŚ
thereâs another thing I hadnât seen suggested, which is a sometimes-handy feature Node introduced a while back; for some expressions they show in a muted color under the current line the current evaluation of that expression. that is, as Iâm typing some code, it prints out the result as if I had hit enter and evaluated it. Iâm not sure how they determine what code they can eagerly evaluate and which would trigger side-effects, but itâs a neat feature.
Thanks @kuba. Seeing your response it now seems obvious, though I realize I misunderstood the link anyway. I thought it was a link to the beta release so I could test vs. actually intending on being a link to the issue tracker.
Would still be nice to update the link to add the URL, but thanks for clearing up my misunderstanding.
I fixed the link - I guess it was âhttps://â missing in post you referred to.
AFAIK, there is no beta release yet and you need to build from master on your own - until there will be RC1 for OTP-26 (probably in February next year).
When working on this PR, I realized that I would like a shell to have some limitations as safeguards in terms of memory consumption, and maybe other resources as well.
Long story: To see if there really was a noticeable difference in terms of runtime between lists:merge(L, [])
and lists:merge([], L)
, I wanted a large list, so I did L=lists:seq(1, 100_000_000)
. Which crashed my shell By crashing the node
If I did that through a remote shell on a production system, for debugging purposes, this "Oops, typo, one zero too many " would instead be âOMG, I just crashed that very important node that has never gone down once in history. Well, yet â
Another thing I noticed when following up on that line (did I mention that I like breaking things? ): If I repeatedly do something like L=lists:seq(1, 10_000_000)
(one zero less than above, doesnât crash right away) at a leisurely pace, all is fine, I can go on for eternity. If I go faster, literally hitting Arrow-Up + Enter as fast as I can, the shell (and node) crashes after a few times. To be clear, the commands are still executed sequentially, one after another, just without any pause in between
With great power, comes great risk! Not saying your suggestion lacks merit, but I think this is a specific example of the generic case of remote shell access (be it Erlang or Linux console) being able to do harm to a running system. In your example, you are doing a performance comparison; performance tests are not something youâd typically want to do on a live system.
(Iâve had past experience of a - sadly - non-Erlang High Availability system where logs being copied off a production server adversely impacted runtime behaviour)