-
-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide APIs to allow users to write their own line editor / interactive interface #663
Comments
|
For context, this issue is related / complementary to #653 but I want to work on both. #653 gives some more immediate benefits while this is a large amount of work that's further in the future. But I think it's important as it will save us the effort of writing 30K lines of code for interactivity -- we just provide the APIs and users can customize the behavior. Much like they do with zsh (but not fish?)
|
Of course I also accept ideas / patches for all of this stuff :) e.g. I think it probably makes sense for shell to have a terminal parser somehow? If we get closer to runnine Maybe the "drawing buffer" needs a special data structure to be fast, etc. And maybe native integers will avoid converting back and forth between strings and ints all the time? I think that the performance of ble.sh must suffer from bash doing that? I imagine you want to stay in the "integer domain" most of the time for performance |
|
In principle, it can be implemented in both strategy, push and pull. But I think push is easier for this situation because pull approach blocks the control when the user input has not yet arrived. It needs additional workarounds such as threads or The implementation of It seems
For LINES and COLUMNS: #include <sys/ioctl.h>
struct winsize ws;
ioctl(tty_fd, TIOCGWINSZ, (char*) &ws);
COLUMNS = ws.ws_col;
LINES = ws.ws_row; The command #include <termios.h>
struct termios termios;
tcgetattr(tty_fd, &termios);
/* modify termios */
tcsetattr(tty_fd, TCSAFLUSH, &termios);
I don't think there is a significant demand for API for terminal parser available from scripts, but
|
Yes I suspected push/pull would be an issue. I don't like having that "mismatch" which is why I like the high-level declarative style -- the you can generate both styles from a specification. re2c apparently supports this, though I haven't used it: https://re2c.org/manual/manual.html#storable-state And actually this ties in very closely to what I think you're doing in https://github.com/oilshell/oil/wiki/Parsing-Shell-Quotes-Requires-Parsing-the-Whole-Language In theory you can imagine "inverting" the whole OSH parser from pull to push, although that sounds a little scary... right now for completion, Oil just parses the entire line again, which is fast. However I can certainly imagine cases for advanced UI where the push/event style (which I presume ble uses) is better. I still want to look at your coroutine abstraction more closely ... It would be nice if you had some short docs / links to source in doc/ because I bet a lot of other people would be interested. This is far in the future, but I would like Oil to have some kind of high level language / DSL for coroutines/state machines, to get rid of the push/pull problem perhaps. I think the ragel state machine generator does the "push" style by default. I noticed Go HTTP libraries are all done in the pull style because the runtime supports goroutines / lightweight threads. As opposed to node.js / nginx in C where they have to write out error prone state machines. So yeah I'm not sure what will happen here but I think it is interesting, and also relates to whether we have |
Another way of saying it is you can divide programmers in two:
I feel like programmers in category 1 usually have some kind of EE background. I used to sit next to a guy doing FPGAs and he said it's all state machines. Most shell programmers (including myself) are probably in category 2. (Although I think Oil is the only shell that encodes IFS as an explicit state machine, in Then again I know that node.js and nginx often have (security) bugs lurking in their HTTP parsing state machine for years ... so it is not easy for anyone. Writing state machines in a higher level language is appealing for that reason. This is all in the future, but I think ble.sh has some very interesting use cases that I will dig deeper into. [1] https://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/ |
Actually I tried the example here in ble.sh and it seems to understand everything? It knows that https://github.com/oilshell/oil/wiki/Parsing-Shell-Quotes-Requires-Parsing-the-Whole-Language Do you think there are cases where it will get confused? How much of shell parsing does it implement? |
Actually I think the example wasn't really showing what I thought it did... I made a note on the wiki page and I will try to come up with some harder examples :) |
push/pull interface
Actually there is a hybrid interface of push/pull or the generalized interface which can be used in both push and pull. I think the famous example is Zlib and other compression libraries (Bzip2, XZ Utils, etc.). For example, you can find this idea in the function declaration of C++ template<typename InternT, typename ExternT, typename State>
result std::codecvt<InternT, ExternT, State>::in(
StateT& state,
const ExternT* from,
const ExternT* from_end,
const ExternT*& from_next,
InternT* to,
InternT* to_end,
InternT*& to_next ) const; Coroutines/fibers in
|
Sorry I meant to test Oil's parser out on all these cases and see what it does, but I haven't had time yet. But I'm impressed! I noted recently that Oil uses its parser for history and completion, but:
http://www.oilshell.org/blog/2020/01/history-and-completion.html It looks like ble.sh is doing a really good job but I haven't tested it more. I would like to provide Oil users with some methods of parsing shell but I haven't figured it out exactly how yet! And the push/pull issue is relevant there. Oil's lexer can be "inverted" with re2c but there's no straightforward way to do that with the parser. BTW Oil has a binding for |
Thank you!
ble.sh uses its parser for completion but doesn't use it for history expansions. Actually, ble.sh doesn't implement the history expansion but just uses
I think some kind of extended
$ blehook
blehook ADDHISTORY=
blehook CHPWD=
blehook DA1R=
blehook DA2R+='ble/term/DA2R.hook'
blehook DA2R+='ble/color/initialize-term-colors'
(snip)
blehook keymap_load+='mshex/my-key-bindings'
blehook keymap_load+='mshex/bashrc/bind-keys'
blehook keymap_vi_load+='ble/util/invoke-hook _ble_keymap_vi_load_hook'
blehook keymap_vi_load+='blerc/vim-load-hook'
blehook keymap_vi_load+='blerc/debug/vim-hook'
blehook syntax_load=
blehook widget_bell+='ble/complete/menu/clear' The detailed usage of the shell function |
Ah I see, I've seen Thanks for the useful observations about the bash APIs. I filed #682 to keep track of that. I think there are some more immediate things on #653, but I would accept patches for builtins based on common usage in That is, I like to design the APIs based on a real usage, i.e. not just imagine what people want. So that is why I think ble.sh is compelling, because it already works and we can extract some APIs from it. A big theme is that a lot of ble.sh is "inverted" vs. a "normal" shell scripts, i.e. in the push/event style. There is heavy use of traps/hooks, etc. That's something I did experience when implementing interactive features in Oil, but I didn't fully appreciate. In other words there are two halves to the shell: the interpreter, and the line editor. And they use opposite paradigms: the intepreter is entirely the "pull" style, and the line editor is almost entirely the "push" style. And in the case of bash, the bridge is very small.
So it's a very thin interface. I think Oil will be richer, but it will also support all the old hooks. |
Great section on how ble.sh works, that I recommend everyone read:
https://github.com/oilshell/oil/wiki/How-Interactive-Shells-Work
The text was updated successfully, but these errors were encountered: