| 1 | ---
 | 
| 2 | default_highlighter: oils-sh
 | 
| 3 | ---
 | 
| 4 | 
 | 
| 5 | Oils Headless Mode: For Alternative UIs
 | 
| 6 | =======================================
 | 
| 7 | 
 | 
| 8 | A GUI or [TUI][] process can start Oils like this:
 | 
| 9 | 
 | 
| 10 |     osh --headless
 | 
| 11 | 
 | 
| 12 | and send messages to it over a Unix domain socket.  In this mode, the language
 | 
| 13 | and shell state are **decoupled** from the user interface.
 | 
| 14 | 
 | 
| 15 | This is a unique feature that other shells don't have!
 | 
| 16 | 
 | 
| 17 | [TUI]: https://en.wikipedia.org/wiki/Text-based_user_interface
 | 
| 18 | 
 | 
| 19 | Note: This doc is **in progress**.  Join the `#shell-gui` channel on
 | 
| 20 | [Zulip]($xref:zulip) for current information.
 | 
| 21 | 
 | 
| 22 | <div id="toc">
 | 
| 23 | </div>
 | 
| 24 | 
 | 
| 25 | ## The General Idea
 | 
| 26 | 
 | 
| 27 | The UI process should handle these things:
 | 
| 28 | 
 | 
| 29 | - Auto-completion.  It should use Oils for parsing, and not try to parse shell
 | 
| 30 |   itself!
 | 
| 31 | - History: Allow the user to retrieve commands typed in the past.
 | 
| 32 | - Cancelling commands in progress.
 | 
| 33 | - Optional: multiplexing among multiple headless shells.
 | 
| 34 | 
 | 
| 35 | The shell process handles these things:
 | 
| 36 | 
 | 
| 37 | - Parsing and evaluating the language
 | 
| 38 | - Maintaining state (shell options, variables, etc.)
 | 
| 39 | 
 | 
| 40 | ## How to Write a Client for a Headless Shell
 | 
| 41 | 
 | 
| 42 | ### Implement the FANOS Protocol
 | 
| 43 | 
 | 
| 44 | FANOS stands for *File descriptors and Netstrings Over Sockets*.  It's a
 | 
| 45 | **control** protocol that already has 2 implementations, which are very small:
 | 
| 46 | 
 | 
| 47 | - [client/py_fanos.py]($oils-src): 102 lines of code
 | 
| 48 | - [native/fanos.c]($oils-src): 294 lines of code
 | 
| 49 | 
 | 
| 50 | ### Send Commands and File Descriptors to the "Server"
 | 
| 51 | 
 | 
| 52 | List of commands:
 | 
| 53 | 
 | 
| 54 | - `EVAL`.  Parse and evaluate a shell command.  The logic is similar to the
 | 
| 55 |   `eval` and `source` builtins.
 | 
| 56 |   - It can be used for both user-entered commands and "behind the scenes"
 | 
| 57 |     functions for the shell UI.
 | 
| 58 |   - The stdin, stdout, and stderr of **the shell and its child processes** will
 | 
| 59 |     be redirected to the descriptors you pass.
 | 
| 60 |   - There's no history expansion for now.  The UI can implement this itself,
 | 
| 61 |     and Oils may be able to help.
 | 
| 62 | 
 | 
| 63 | TODO: More commands.
 | 
| 64 | 
 | 
| 65 | ### Query Shell State and Render it in the UI
 | 
| 66 | 
 | 
| 67 | You may want to use commands like these to draw the UI:
 | 
| 68 | 
 | 
| 69 | - `echo ${PS1@P}` -- render the prompt
 | 
| 70 | - `echo $PWD $_` -- get the current directory and current status
 | 
| 71 | 
 | 
| 72 | You can redirect them to a pipe, rather than displaying them in the terminal.
 | 
| 73 | 
 | 
| 74 | Remember that a fundamental difference between a REPL and a GUI is that a GUI
 | 
| 75 | **shows state** explicitly.  This is a good thing and you should take advantage
 | 
| 76 | of it!
 | 
| 77 | 
 | 
| 78 | ### Example Code
 | 
| 79 | 
 | 
| 80 | See [client/headless_demo.py]($oils-src).  This is pure Python code that's
 | 
| 81 | divorced from the rest of Oils.
 | 
| 82 | 
 | 
| 83 | ## Related Links
 | 
| 84 | 
 | 
| 85 | Feel free to edit these pages:
 | 
| 86 | 
 | 
| 87 | - [Headless Mode][] on the wiki.  We want there to be a rich ecosystem of
 | 
| 88 |   interactive shells built upon Oils.
 | 
| 89 | - [Interactive Shell][] on the wiki.  Be inspired by these nice projects, many
 | 
| 90 |   of which have screenshots! 
 | 
| 91 | 
 | 
| 92 | [Headless Mode]: https://github.com/oilshell/oil/wiki/Headless-Mode
 | 
| 93 | 
 | 
| 94 | [Interactive Shell]: https://github.com/oilshell/oil/wiki/Interactive-Shell
 |