From 75c496c51f75355bbccfd088f5521bee20a26be3 Mon Sep 17 00:00:00 2001 From: josuah Date: Sat, 29 Oct 2016 04:01:02 -0400 Subject: [PATCH] Added draft for the completion framework --- Makefile | 9 +- example | 19 ++ iocomplete | 27 ++ iocomplete.1 | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ioshell | 3 + main.c | 40 +-- 6 files changed, 943 insertions(+), 22 deletions(-) create mode 100644 example create mode 100644 iocomplete create mode 100644 iocomplete.1 create mode 100644 ioshell diff --git a/Makefile b/Makefile index 8e17f66..7172ee7 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,15 @@ CFLAGS = -std=c89 -pedantic -Wall -Wextra -g -all: iomenu +all: clean iomenu iomenu: - cc main.c -o $@ $(CFLAGS) + $(CC) main.c -o $@ $(CFLAGS) clean: - rm iomenu + rm -f iomenu install: iomenu cp iomenu $(PREFIX)/bin/iomenu + +.PHONY: all clean install + diff --git a/example b/example new file mode 100644 index 0000000..af4eedf --- /dev/null +++ b/example @@ -0,0 +1,19 @@ +-terse o terse output +-pretty o pretty output +-mode o output mode +-colors o whether to use colors in output +-fields o specify fields to output +-escape o escape columns separators in values +-ask o ask for missing parameters +-show-secrets o allow displaying passwords +-wait o set timeout waiting for finishing operations +-version o show program version +-help o print this help +general o NetworkManager's general status and operations +networking o overall networking control +radio o NetworkManager radio switches +connection o NetworkManager's connections +device o devices managed by NetworkManager +agent o NetworkManager secret agent or polkit agent +monitor o monitor NetworkManager changes +help o diff --git a/iocomplete b/iocomplete new file mode 100644 index 0000000..77d2f35 --- /dev/null +++ b/iocomplete @@ -0,0 +1,27 @@ +# Complete the input with a completion tree directory. + +# o option +# check if there is a subdirectory with this label. If so, start the +# prompt again with this list, otherwise, come back to the main loop +# +# f flag +# +# +# p path +# prompt for path in another loop, then start the main loop +# +# r raw +# let the user input some value directly, without option +# + +nmcli top directory with the same name as the command +| +`- FLAGS flags to pass as command line arguments to iomenu +| +`- COMPLETION completion file with the common options +| +`- -mode if some option has sub-options, add one file per option name +| +`- networking if some option has sub-options and sub-sub-options, add one + directory per option name, and add the same file structure + in it. diff --git a/iocomplete.1 b/iocomplete.1 new file mode 100644 index 0000000..009de34 --- /dev/null +++ b/iocomplete.1 @@ -0,0 +1,867 @@ +.Dd $Mdocdate: September 28 2016 $ +.Dt IOCOMPLETE 1 +.Os +.Sh NAME +. +.Nm iocomplete +.Nd a command line completion backend for iomenu +. +.Sh SYNOPSIS +. +.Nm +.Op + + +.Op Ic +command +.Op Ar files Fl +. +.Sh DESCRIPTION +. +.Nm vis +is a highly efficient vim like text editor. +.Bl -tag +.It Fl v +Print version information and exit. +. +.It Fl - +Denotes the end of the options. Arguments after this will be handled as a +file name. +.El +. +.Ss Modes +. +Vis implements more or less functional normal, operator-pending, insert, +replace and visual (in both line and character wise variants) modes. +.Pp +Visual block mode is not implemented and there exists no immediate plan +to do so. Instead vis has built in support for multiple cursors. +.Pp +Command mode is implemented as a regular file. Use the full power of +the editor to edit your commands / search terms. +.Pp +Ex mode is deliberately not implemented, instead a variant of the +structural regular expression based command language of `sam(1)` +is supported. +. +.Ss Undo/Redo and Repeat +. +The text is currently snapshotted whenever an operator is completed as +well as when insert or replace mode is left. Additionally a snapshot is +also taken if in insert or replace mode a certain idle time elapses. +.Pp +Another idea is to snapshot based on the distance between two consecutive +editing operations (as they are likely unrelated and thus should be +individually reversible). +.Pp +Besides the regular undo functionality, the key bindings +.Ql g+ +and +.Ql g- +traverse the history in chronological order. Further more the +.Iq :earlier +and +.Iq :later +commands provide means to restore the text to an arbitrary +state. +.Pp +The repeat command +.Ql \&. +works for all operators and is able to repeat +the last insertion or replacement. +. +.Ss Tab <-> Space conversion and Line endings \n vs \r\n +. +Tabs can optionally be expanded to a configurable number of spaces. +The first line ending in the file determines what will be inserted upon +a line break (defaults to \n). +. +.Ss Jump list and change list +. +A per window, file local jump list (navigate with `CTRL+O` and `CTRL+I`) +and change list (navigate with `g;` and `g,`) is supported. The jump +list is implemented as a fixed sized ring buffer. +. +.Ss Macros +. +The general purpose registers +.Ql [a-z] +can be used to record macros. Use +one of +.Ql [A-Z] +to append to an existing macro. +.Ql q +starts a recording, +.Ql @ +plays it back. +.Ql @@ +refers to the least recently recorded macro. +.Ql @: +repeats the last :-command. +.Ql @/ +is equivalent to +.Ql n +in normal mode. +. +.Ss Structural Regular Expression based Command Language +. +.Nm vis +supports +.Xr sam 1 +structural regular expression based command language. +. +.Ss Mouse support +. +. +.Sh KEY BINDINGS +. +.Ss Operators +. +.Bl -tag +.It c +change +. +.It d +delete +. +.It ! +filter +. +.It = +indent, currently an alias for gq +. +.It gq +format using fmt(1) +. +.It gu +make lowercase +. +.It gU +make uppercase +. +.It J +join +. +.It p +put +. +.It < +shift-left +. +.It > +shift-right +. +.It ~ +swap case +. +.It y +yank +.El +. +.Ss Movements +. +.Bl -tag +.It 0 +start of line +. +.It b +previous start of a word +. +.It B +previous start of a WORD +. +.It $ +end of line +. +.It e +next end of a word +. +.It E +next end of a WORD +. +.It F char +to next occurrence of char to the left +. +.It f char +to next occurrence of char to the right +. +.It ^ +first non-blank of line +. +.It g0 +begin of display line +. +.It g$ +end of display line +. +.It ge +previous end of a word +. +.It gE +previous end of a WORD +. +.It gg +begin of file +. +.It G +goto line or end of file +. +.It gj +display line down +. +.It gk +display line up +. +.It g_ +last non-blank of line +. +.It gm +middle of display line +. +.It | +goto column +. +.It h +char left +. +.It H +goto top/home line of window +. +.It j +line down +. +.It k +line up +. +.It l +char right +. +.It L +goto bottom/last line of window +. +.It ` mark +go to mark +. +.It ' mark +go to start of line containing mark +. +.It % +match bracket +. +.It M +goto middle line of window +. +.It ]] +next end of C-like function +. +.It } +next paragraph +. +.It ) +next sentence +. +.It ][ +next start of C-like function +. +.It N +repeat last search backwards +. +.It n +repeat last search forward +. +.It [] +previous end of C-like function +. +.It [{ +previous start of block +. +.It ]} +next start of block +. +.It [( +previous start of parenthese pair +. +.It ]) +next start of parenthese pair +. +.It { +previous paragraph +. +.It ( +previous sentence +. +.It [[ +previous start of C-like function +. +.It ; +repeat last to/till movement +. +.It , +repeat last to/till movement but in opposite direction +. +.It # +search word under cursor backwards +. +.It * +search word under cursor forwards +. +.It T char +till before next occurrence of char to the left +. +.It t char +till before next occurrence of char to the right +. +.It ? text +to next match of text in backward direction +. +.It / text +to next match of text in forward direction +. +.It w +next start of a word +. +.It W +next start of a WORD +.El +.Pp +An empty line is currently neither a word nor a WORD. +.Pp +Some of these commands do not work as in vim when prefixed with a +digit i.e. a multiplier. As an example in vim +.Ql 3$ +moves to the end +of the 3rd line down. However vis treats it as a move to the end of +current line which is repeated 3 times where the last two have no +effect. +. +.Ss Text objects +. +All of the following text objects are implemented in an inner variant +(prefixed with +.Ql i`) and a normal variant (prefixed with +.Ql a`): +.Bl -tag +. +.It w +word +. +.It W +WORD +. +.It s +sentence +. +.It p +paragraph +. +.It [,], (,), {,}, <,>, ", ', ` +block enclosed by these symbols +.El +.Pp +For sentence and paragraph there is no difference between the inner and +normal variants. +.Bl -tag +. +.It gn +matches the last used search term in forward direction +. +.It gN +matches the last used search term in backward direction +.El +.Pp +Additionally the following text objects, which are not part of stock +vim are also supported: +.Bl -tag +. +.It ae +entire file content +. +.It ie +entire file content except for leading and trailing empty lines +. +.It af +C-like function definition including immediately preceding comments +. +.It if +C-like function definition only function body +. +.It al +current line +. +.It il +current line without leading and trailing white spaces +.El +. +.Ss Multiple Cursors / Selections +. +.Nm vis +supports multiple cursors with immediate visual feedback (unlike in the +visual block mode of vim where for example inserts only become visible +upon exit). There always exists one primary cursor located within the +current view port. Additional cursors ones can be created as needed. If +more than one cursor exists, the primary one is styled differently +(yellow by default). +.Pp +To manipulate multiple cursors use in normal mode: +.Bl -tag +. +.It Ctrl-K +create count new cursors on the lines above +. +.It Ctrl-Meta-K +create count new cursors on the lines above the first cursor +. +.It Ctrl-J +create count new cursors on the lines below +. +.It Ctrl-Meta-J +create count new cursors on the lines below the last cursor +. +.It Ctrl-P +remove primary cursor +. +.It Ctrl-N +select word the cursor is currently over, switch to visual mode +. +.It Ctrl-U +make the count previous cursor primary +. +.It Ctrl-D +make the count next cursor primary +. +.It Ctrl-C +remove the count cursor column +. +.It Ctrl-L +remove all but the count cursor column +. +.It Tab +try to align all cursor on the same column +. +.It Esc +dispose all but the primary cursor +.El +.Pp +Visual mode was enhanced to recognize: +.Bl -tag +. +.It I +create a cursor at the start of every selected line +. +.It A +create a cursor at the end of every selected line +. +.It Tab +left align selections by inserting spaces +. +.It Shift-Tab +right align selections by inserting spaces +. +.It Ctrl-N +create new cursor and select next word matching current selection +. +.It Ctrl-X +clear (skip) current selection, but select next matching word +. +.It Ctrl-P +remove primary cursor +. +.It Ctrl-U/K +make the count previous cursor primary +. +.It Ctrl-D/J +make the count next cursor primary +. +.It Ctrl-C +remove the count cursor column +. +.It Ctrl-L +remove all but the count cursor column +. +.It + +rotates selections rightwards count times +. +.It - +rotates selections leftwards count times +. +.It \e +trim selections, remove leading and trailing white space +. +.It Esc +clear all selections, switch to normal mode +.El +.Pp +In insert/replace mode: +.Bl -tag +. +.It Shift-Tab +align all cursors by inserting spaces +.El +. +.Ss Marks +. +.Bl -tag +. +.It [a-z] +general purpose marks +. +.It < +start of the last selected visual area in current buffer +. +.It > +end of the last selected visual area in current buffer +.El +. +.Ss Registers +. +Supported registers include: +.Bl -tag +. +.It "a-"z +general purpose registers +. +.It "A-"Z +append to corresponding general purpose register +. +.It "*, +"+ system clipboard integration via shell script vis-clipboard +. +.It "0 +yank register +. +.It "/ +search register +. +.It ": +command register +. +.It "_ +black hole (/dev/null) register +.El +.Pp +If no explicit register is specified a default register is used. +. +.Sh COMMANDS +. +.Pp +Besides the sam command language the following commands are also recognized at +the `:`-command prompt. Any unique prefix can be used. +.Bl -tag +.Iq :bdelete +close all windows which display the same file as the current one +.Iq :earlier +revert to older text state +.Iq :e +replace current file with a new one or reload it from disk +.Iq :langmap +set key equivalents for layout specific key mappings +.Iq :later +revert to newer text state +.Iq :! +launch external command, redirect keyboard input to it +.Iq :map +add a global key mapping +.Iq :map-window +add a window local key mapping +.Iq :new +open an empty window, arrange horizontally +.Iq :open +open a new window +.Iq :qall +close all windows, exit editor +.Iq :q +close currently focused window +. +.It :r +insert content of another file at current cursor position +. +.It :set +set the options below +. +.It :split +split window horizontally +. +.It :s +search and replace currently implemented in terms of `sed(1)` +. +.It :unmap +remove a global key mapping +. +.It :unmap-window +remove a window local key mapping +. +.It :vnew +open an empty window, arrange vertically +. +.It :vsplit +split window vertically +. +.It :wq +write changes then close window +. +.It :w +write current buffer content to file +. +.It tabwidth [1-8] default 8 +set display width of a tab and number of spaces to use if expandtab is enabled +. +.It expandtab (yes|no) default no +whether typed in tabs should be expanded to tabwidth spaces +. +.It autoindent (yes|no) default no +replicate spaces and tabs at the beginning of the line when +. +.It number (yes|no) default no +. +.It relativenumber (yes|no) default no +whether absolute or relative line numbers are printed alongside +. +.It syntax name default yes +use syntax definition given (e.g. "c") or disable syntax +. +.It show +show/hide special white space replacement symbols +.Bl -bullet +. +.It +newlines = [0|1] default 0 +. +.It +tabs = [0|1] default 0 +. +.It +spaces = [0|1] default 0 +.El +. +.It cursorline (yes|no) default no +highlight the line on which the cursor currently resides +. +.It colorcolumn number default 0 +highlight the given column +. +.It horizon number default 32768 (32K) +how far back the lexer will look to synchronize parsing +. +.It theme name default dark-16.lua | solarized.lua (16 | 256 color) +use the given theme / color scheme for syntax highlighting +.El +.Pp +Commands taking a file name will use a simple file open dialog based on +the included `vis-open` shell script and `vis-menu` utility, if given +a file pattern or directory. +.Ic :e *.c +opens a menu with all C files +.Ic :e \&. +opens a menu with all files of the current directory +. +.Ss Runtime Configurable Key Bindings +. +Vis supports run time key bindings via the +.Ic :{un,}map{,-window} +set of commands. The basic syntax is +.Ic :map +where mode is one of +.Ql normal +, +.Ql insert +, +.Ql replace +, +.Ql visual +, +.Ql visual-line +or +.Ql operator-pending +. +.Ql lhs +refers to the key to map, +.Ql rhs +is a key action or alias. An existing mapping can be overridden by appending +.Ql ! +to the map command. +.Pp +Key mappings are always recursive, this means doing something like +.Ic :map! normal j 2j +will not work because it will enter an endless loop. Instead vis uses +pseudo keys referred to as key actions which can be used to invoke a set +of available (see +.Ic :help +or +.Ic F1 +for a list) editor functions. Hence the correct thing to do would be +.Ic :map! normal j 2 +.Pp +Unmapping works as follows: +.Ic :unmap +.Pp +The commands suffixed with `-window` only affect the currently active window. +. +.Ss Layout Specific Key Bindings +. +Vis allows to set key equivalents for non-latin keyboard layouts. This +facilitates editing non-latin texts. The defined mappings take effect +in all non-input modes, i.e. everywhere except in insert and replace mode. +.Pp +For example, the following maps the movement keys in Russian layout: +.Ic :langmap ролд hjkl +.Pp +More generally the syntax of the `:langmap` command is: +.Ic :langmap +.Pp +If the key sequences have not the same length, the rest of the longer +sequence will be discarded. +. +.Ss Runtime Configurable Key Bindings +. +Vis supports run time key bindings via the +.Ic :{un,}map{,-window} +set of commands. The basic syntax is +.Ic :map +where mode is one of +.Ql normal +, +.Ql insert +, +.Ql replace +, +.Ql visual +, +.Ql visual-line +or +.Ql operator-pending +. +.Ql lhs +refers to the key to map, +.Ql rhs +is a key action or alias. An existing mapping can be overridden by appending +.Ql ! +to the map command. +.Pp +Key mappings are always recursive, this means doing something like +.Ic :map! normal j 2j +will not work because it will enter an endless loop. Instead vis uses +pseudo keys referred to as key actions which can be used to invoke a set +of available (see +.Ic :help +or +.Ic F1 +for a list) editor functions. Hence the correct thing to do would be +.Ic :map! normal j 2 +.Pp +Unmapping works as follows: +.Ic :unmap +.Pp +The commands suffixed with `-window` only affect the currently active window. +. +.Ss Layout Specific Key Bindings +. +Vis allows to set key equivalents for non-latin keyboard layouts. This +facilitates editing non-latin texts. The defined mappings take effect +in all non-input modes, i.e. everywhere except in insert and replace mode. +.Pp +For example, the following maps the movement keys in Russian layout: +.Ic :langmap ролд hjkl +.Pp +More generally the syntax of the `:langmap` command is: +.Ic :langmap +.Pp +If the key sequences have not the same length, the rest of the longer +sequence will be discarded. +. +.Sh ENVIRONMENT +. +.Bl -tag +.Ev VIS_PATH +Override path to look for Lua support files as used for syntax highlighting. +Defaults (in this order) to: +.Bl -bullet +. +.It +The location of the vis binary +. +.It +.Pa $XDG_CONFIG_HOME/vis +where +.Ev $XDG_CONFIG_HOME +refers to +.Pa $HOME/.config +if unset +. +.It +.Pa /usr/local/share/vis +. +.It +.Pa /usr/share/vis +.El +.Ev VIS_THEME +Override syntax highlighting theme to use. +.El +. +.Sh FILES +. +.Pp +Settings and keymaps can be specified in a +.Pa visrc.lua +file, which will +be read by +.Pa vis +at runtime. An example +.Pa visrc.lua +file is installed in +.Pa /usr/local/share/vis +by default. This file can be copied to +.Pa $XDG_CONFIG_HOME/vis +(which defaults to +.Pa $HOME/.config/vis +) for further configuration. +.Pp +The environment variable +.Pa VIS_PATH +can be set to override the path that +.Pa vis +will look for Lua support files as used for syntax highlighting. +.Pa VIS_PATH +defaults (in this order) to: +.Bl -bullet +. +.It +The location of the +.Nm vis +binary +. +.It +.Pa $XDG_CONFIG_HOME/vis +where +.Pa $XDG_CONFIG_HOME +refers to +.Pa $HOME/.config +if unset. +. +.It +.Pa /usr/local/share/vis +. +.It +.Pa /usr/share/vis +.El +.Pp +The environment variable +.Ev VIS_THEME +can be set to specify the theme used by +.Nm vis +: +.Bd -literal +VIS_THEME=/path/to/your/theme.lua +export VIS_THEME +.Ed +. +.Sh SEE ALSO +. +.Xr vis-menu 1 +.Xr vis-open 1 +.Xr vis-clipboard 1 +.Xr vis-complete 1 +. +.Sh AUTHORS +. +.Nm vis +is written by +.An Marc André Tanner Aq mat at brain-dump.org diff --git a/ioshell b/ioshell new file mode 100644 index 0000000..b11820c --- /dev/null +++ b/ioshell @@ -0,0 +1,3 @@ +# Repeatedly run iocomplete to act as a shell + +# Pipe the output in less -R all of time. diff --git a/main.c b/main.c index d442fc8..a9cb9e8 100644 --- a/main.c +++ b/main.c @@ -39,7 +39,6 @@ fill_buffer(char *separator) char string[LINE_SIZE]; Line *last = NULL; Buffer *buffer = malloc(sizeof(Buffer)); - /* FILE *fp = fopen("/dev/stdin", "r"); */ FILE *fp = stdin; if (!fp) { @@ -332,10 +331,10 @@ print_lines(Buffer *buffer, int count, int offset, int cols) * This also has to clear the previous lines. */ void -update_screen(Buffer *buffer, int count, int offset, int tty) +update_screen(Buffer *buffer, int count, int offset, int tty_fd) { struct winsize w; - ioctl(tty, TIOCGWINSZ, &w); + ioctl(tty_fd, TIOCGWINSZ, &w); count = MIN(count, w.ws_row - 2); fputs("\n", stderr); @@ -361,7 +360,7 @@ void clear_screen(int count) * last terminal state. */ struct termios -terminal_set(int tty) +set_terminal(int tty_fd) { struct termios termio_old; struct termios termio_new; @@ -369,7 +368,7 @@ terminal_set(int tty) /* set the terminal to send one key at a time. */ /* get the terminal's state */ - if (tcgetattr(tty, &termio_old) < 0) { + if (tcgetattr(tty_fd, &termio_old) < 0) { die("Can not get terminal attributes with tcgetattr()."); } @@ -378,7 +377,7 @@ terminal_set(int tty) termio_new.c_lflag &= ~(ICANON | ECHO | IGNBRK); /* apply this state to current terminal now (TCSANOW) */ - tcsetattr(tty, TCSANOW, &termio_new); + tcsetattr(tty_fd, TCSANOW, &termio_new); return termio_old; } @@ -387,22 +386,22 @@ terminal_set(int tty) * Listen for the user input and call the appropriate functions. */ void -get_input(Buffer *buffer, int count, int offset, int tty) +get_input(Buffer *buffer, int count, int offset, int tty_fd) { - FILE *tty_fd = fopen("/dev/tty", "r"); + FILE *tty_fp = fopen("/dev/tty", "r"); /* receive one character at a time from the terminal */ - struct termios termio_old = terminal_set(tty); + struct termios termio_old = set_terminal(tty_fd); /* get input char by char from the keyboard. */ - while (do_key(fgetc(tty_fd), buffer)) { - update_screen(buffer, count, offset, tty); + while (do_key(fgetc(tty_fp), buffer)) { + update_screen(buffer, count, offset, tty_fd); } /* resets the terminal to the previous state. */ - tcsetattr(tty, TCSANOW, &termio_old); + tcsetattr(tty_fd, TCSANOW, &termio_old); - fclose(tty_fd); + fclose(tty_fp); } /* @@ -617,12 +616,12 @@ print_prompt(Buffer *buffer, int cols) /* * Reset the terminal state and exit with error. */ -void die(const char *s) +void +die(const char *s) { -/* tcsetattr(STDIN_FILENO, TCSANOW, &termio_old); */ + /* tcsetattr(STDIN_FILENO, TCSANOW, &termio_old); */ fprintf(stderr, "%s\n", s); exit(EXIT_FAILURE); - } int @@ -631,7 +630,7 @@ main(int argc, char *argv[]) int i; Buffer *buffer = NULL; int offset = 3; - int tty = open("/dev/tty", O_RDWR); + int tty_fd = open("/dev/tty", O_RDWR); /* command line arguments */ for (i = 0; i < argc; i++) { @@ -671,12 +670,15 @@ main(int argc, char *argv[]) /* set the interface */ filter_lines(buffer); - update_screen(buffer, opt_lines, offset, tty); + update_screen(buffer, opt_lines, offset, tty_fd); /* listen and interact to input */ - get_input(buffer, opt_lines, offset, tty); + get_input(buffer, opt_lines, offset, tty_fd); clear_screen(opt_lines); + /* close files descriptors and pointers, and free memory */ + close(tty_fd); + return 0; } -- 2.11.4.GIT