8 ms·
Bestline: Light self-contained readline alternative
- yjftsjthsd-h 5y agoSo I think (having read the readme but not the code and not being expert in the subject matter) this is a library that lets you do things like read line, but probably is not API or ABI compatible (because that seems like something that would be mentioned and I can't see anything about it)? Also, I have to say I'm entertained at completely throwing out worrying about terminals and just declaring that everything supports vt100 so we're going to target that and be done with it. Kinda elegant, especially for the relatively limited functionality they need (not like it's curses where you're really going to exercise the terminal's capabilities).
- nine_k 5y agoI suppose there are two kinds of terminals in real use today: terminal emulators (which all support vt100) and dumb / trivial consoles that use a framebuffer if not a segmented LCD display, that don't support anything standardized anyway, and you don't need much from them beside displaying characters. So the choice to support the common case of the terminal emulator looks reasonable. Even when you attach a serial cable to a tiny controller to do something on its tiny command line, you likely do it from your laptop. Having a readline lookalike in this situation would be nice.
- JoshTriplett 5y agoLooks like this doesn't support Ctrl-O (run line and retrieve next line from history). I've found that incredibly useful for re-running a series of commands: Ctrl-R to reverse search, type a few letters, Ctrl-O Ctrl-O Ctrl-O.
- stevekemp 5y agoThe one shortcut I use the most, in addition to the listed ones, is "Ctrl-e Ctrl-e" which opens an editor then sends the resulting content to the shell. Using an editor is great for loops, loops with nested conditions, etc.
- nine_k 5y agoHmm, does not work for me; Ctrl+X Ctrl+E does, as expected. (Be sure to set VISUAL to something nice.)
- stevekemp 5y agoSorry yes I made a mistake, and too late to edit!
- MaxBarraclough 5y agoHere's a (rather less sophisticated) personal favourite of mine: alt + # causes a # symbol to be prepended to the line, and then runs it. Useful for entering a nearly-finished line into your command history for later, commented out, if you realise you need to fix up something else beforehand. Slightly faster than ctrl-a followed by # followed by return.
- masklinn 5y agoI usually use C-q for that: it stores the current line in a buffer which it restores after the next execution.
- MaxBarraclough 5y agoOn my machine, ctrl-q appears to do nothing. (Aside: I've never seen the sense in using C to denote ctrl. How do you denote C?)
- masklinn 5y ago> On my machine, ctrl-q appears to do nothing. Ah apparently it's a ZSH-specific shortcut for "push-line". readline follows Emacs' (not illogical but probably less useful here) "quoted-insert" (generally used to include non-literal code e.g. C-q a does nothing as "a" is already literal, but C-q C-q should insert 0x 11 / XON / DC1). > (Aside: I've never seen the sense in using C to denote ctrl. How do you denote C?) c. Or C for S-c (shift-c). a-b indicates a single keystroke, meaning a modified key, so the first character can only signify a modifier key[0]. Which "c" is not. The sequence "upper case C then lowercase c" is "C c", not "C-c". [0] well technically you could have keystrokes of non-modifiers as modern keyboards can handle concurrent keycodes, but historical systems don't so a keystroke is only a bunch of modifiers + a single key e.g. C-S-M-c is unambiguously Control-Shift-Meta-c
- riffraff 5y agoWow, I didn't know about this, thanks so much!
- atommclain 5y agoThis is cool, thanks for sharing! I have the following in my .inputrc which is in a similar vein (may be an anti pattern): ``` # F1, F2, F3 - calls alias1, alias2, alias3, helpful if you are executig the same ommands over and over "^[OP": "alias1\r" "^[OQ": "alias2\r" "^[OR": "alias3\r" ```
- chubot 5y agoHm I don't see mention of vi key bindings? set -o vi is awesome in bash / Python / R, etc.
- mediocregopher 5y agoThe README mentions Antirez's coding philosophy as being an inspiration: > This codebase aims to follow in Antirez's tradition of writing beautiful programs, that solve extremely difficult difficult technical problems in the simplest most elegant way possible. Is something Antirez has talked about himself anywhere? I'm interested to know more, but am not fluent enough in C to understand what makes this code elegant.
- IgorPartola 5y agoI didn’t dive deep into this code but what I would assume makes this elegant is that it is mostly declarative/lookup style with only a little imperative code where necessary. This style doesn’t use fancy tricks/hacks and instead uses lookup tables where necessary to encapsulate logic.
- jks 5y agoThis library is a fork of Antirez's linenoise, so it's perhaps not only an inspiration but a quality that the code had to begin with, which the author of the fork declares that she intends to preserve. The linenoise README mentions "sensibility for small easy to understand code". It's not really explained further in the README, but I suppose the point is that you can read the ~1200 lines of source code and get a feel for it yourself.
- cloudbonsai 5y agoTbh, it doesn't seem to me like a great code. https://github.com/jart/bestline/blob/master/bestline.c#L2865 https://github.com/jart/bestline/blob/master/bestline.c#L286... This interface function is already terrible. Why doesn't it check the error code of bestlineHistoryLoad()? It smells like a sloppy C program with obscure failure modes.
- nrdvana 5y agoOpen this code side by side with the source code for Cyrus IMAP, or Perl core, or libssl, and then scroll through them. You will be enlightened. In short, any code that is intended to work on a wide variety of systems is usually littered with conditional compilation directives and macros that make the code extremely difficult to follow without a extensive study of the author’s “setup”. This is because to compile/run on a wide variety of systems, you actually need wildly different C source code, and what is written in the C source file ends up being more like a template for a program than the actual program.
- savolai 5y agoCurious about the UI paradigm here and still newbie after all these years. Is there a well written explanation about the idea / logic behind the terminology of kill line / yank somewhere for people who are used to ... well, just what modern GUIs provide, i.e copy/paste etc? Pros/cons? What functionality do these operations actually provide? Thanks.
- jks 5y agoThe terminology comes from Emacs: https://www.emacswiki.org/emacs/KillingAndYanking https://www.emacswiki.org/emacs/KillingAndYanking https://www.gnu.org/software/emacs/manual/html_node/emacs/Killing.html https://www.gnu.org/software/emacs/manual/html_node/emacs/Ki... The basic idea is that your clipboard ("kill ring") can contain many entries, so you can kill several lines (or words, sentences, functions, what have you) and then yank them back at other locations. Yanking copies the most recently killed text, but you can use another command to replace it with previous entries until you find the right one. Thus you don't have to fear losing the clipboard while performing intermediate operations. Readline-type libraries typically implement a small subset of the Emacs kill-ring features, so you really need to try Emacs to appreciate the full range of the concept.
- nine_k 5y agoFor instance, the kill ring allows you to easily move around two words in different parts of a long command. - Move cursor to the first word, kill it with Alt+D (aka M-D). - Fearlessly move the cursor to another word, kill it, too. - Now move where you want to put the first word back, because it's nearby. Press Ctrl+Y, oops, it shows the second word. Never mind, press Alt+Y, and it pastes the first word on its place. - Now move elsewhere where the second word belongs. Ctrl+Y pastes (yanks) the first word again, the most recently used. Alt+Y changes it to the second word, the second most recently used. This way you may have quite a few fragments in the ring and juggle them, repeat them, several different fragments, without the need to copy again and again.
- savolai 5y agoThanks. I suppose I would have to see this in practice to be able to understand and appreciate it. My memory is limited so it doesn't seem worth the trouble to learn such a niche system. Still there's something intriguing about it as someone who tries to keep one's mind open about different design systems. As a ui/ux designer what strikes me with these legacy systems is there seems to be no fluent support system in place for learning them. And even after you've learned, no visibility to support long term memorization. Also, I suppose there is no clear visual panel to support memory as to what's actually in the ring but you kinda have to just browse it one by one with shortcuts, as I understand the above? Do the terms kill/yank seem appropriate to others? It seems that there is a slang context I'm missing there that might make the terms more intuitive.
- maddyboo 5y agoIt would be cool to see a version of rlwrap [1] (blwrap in this case?) using this library. [1]: https://man.archlinux.org/man/rlwrap.1 https://man.archlinux.org/man/rlwrap.1
- hanslub42 5y agoWhat advantages would a blwrap have over rlwrap? As I understand it, bestline's advantages over readline (fewer dependencies, license) only apply when you are using it as a library. rlwrap is a separate program that weighs in at around 200k. That could only ever be a problem on an embedded system, where rlwrap/blwrap wouldn't make sense anyway.
- swetland 5y agoI'm a bit puzzled by "reducing binary footprint (surprisingly) by removing bloated dependencies" since linenoise has no dependencies (beyond libc) that I'm aware of. $ size linenoise_example text data bss dec hex filename 14718 948 184 15850 3dea linenoise_example $ size bestline_example text data bss dec hex filename 40830 1000 9280 51110 c7a6 bestline_example Which seems reasonable since bestline has a bunch of unicode tables and handling for a bunch of editing features beyond linenoise's minimalist featureset, but I still don't understand the "bloated dependencies" remark...
- masklinn 5y agoThe readme mentions > Remove heavyweight dependencies like printf/sprintf But that’s from libc, unless they measure by statically linking everything?
- _ph_ 5y agoWhen you think about using the library from languages which don't link against libc by default (Go for example), then this is a significant difference.
- masklinn 5y agoHow does Go have any relevance? This is a C program, it will link against libc.
- R0b0t1 5y agoThe example is still relevant, say if your program has no OS.
- masklinn 5y ago> The example is still relevant, say if your program has no OS. Not only does it seem unlikely your program would have a terminal output and standard streams without having an OS, bestline still requires a libc. Just open `bestline.c` and you'll find: #include <termios.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <unistd.h> #include <setjmp.h> #include <poll.h> #include <assert.h> #include <signal.h> #include <fcntl.h> #include <limits.h>
- lume 5y agoTrying to compile it on osx. Several errors like this: make cc -I/usr/local/opt/ruby/include -c -o bestline.o bestline.c In file included from bestline.c:122: In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/termios.h:26: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:681:49: error: invalid token at start of a preprocessor expression #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1L ^
- Miiko 5y agoApparently, it does not fully conforms to POSIX as README claims - AFAIK, that "_POSIX_X_SOURCE" feature test macro should be defined with positive integer value per POSIX standard, not empty as defined in bestline.c
- jart 5y agoThe issue you encountered should be fixed! I've confirmed it's building on Mac OS X. Enjoy.
- laumars 5y agoAt this point there are already hundreds of readline alternatives across various different languages as it’s actually surprisingly easy to write a readline library. Given the capabilities of computers these days, I think if one is stuck choosing which library to use, I’d suggest get the one that’s most complete rather than most compact. I guarantee you that there will be one of your users who’ll use an Emacs or Vi shortcut and find the lack of support really prohibiting.
- melezhik 5y agoI have added bestline to "my butterflies", independent software reviews site, http://161.35.115.119/mbf/project/bestline/reviews http://161.35.115.119/mbf/project/bestline/reviews , one can vote, write reviews here as well.