diff options
author | p-gen <p.gen.progs@gmail.com> | 2015-08-09 23:00:59 +0200 |
---|---|---|
committer | p-gen <p.gen.progs@gmail.com> | 2015-08-09 23:00:59 +0200 |
commit | 3b1efafd57c5ff498463fc725c31cddcf1a01f57 (patch) | |
tree | d04c06843b83d3d13fbe2e48c9d3349f3a7fb053 |
First commit.v0.9
-rw-r--r-- | .indent.pro | 38 | ||||
-rw-r--r-- | COPYRIGHT | 3 | ||||
-rw-r--r-- | INTERNALS.rst | 56 | ||||
-rw-r--r-- | LICENSE.md | 264 | ||||
-rw-r--r-- | Makefile | 57 | ||||
-rw-r--r-- | README.rst | 102 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | smenu.1 | 255 | ||||
-rw-r--r-- | smenu.c | 3737 | ||||
-rw-r--r-- | smenu.h | 84 | ||||
-rw-r--r-- | version | 1 |
11 files changed, 4601 insertions, 0 deletions
diff --git a/.indent.pro b/.indent.pro new file mode 100644 index 0000000..4632183 --- /dev/null +++ b/.indent.pro @@ -0,0 +1,38 @@ +--blank-lines-after-commas +--declaration-comment-column 30 +--brace-indent 0 +--braces-after-if-line +--braces-after-struct-decl-line +--break-after-boolean-operator +--case-brace-indentation 0 +--case-indentation 2 +--continue-at-parentheses +--declaration-indentation 2 +--dont-break-procedure-type +--dont-cuddle-do-while +--dont-cuddle-else +--dont-format-first-column-comments +--dont-space-special-semicolon +--honour-newlines +--indent-level 2 +--leave-optional-blank-lines +--line-length 80 +--no-blank-lines-before-block-comments +--no-comment-delimiters-on-blank-lines +--no-space-after-function-call-names +--no-space-after-parentheses +--no-tabs +--no-blank-lines-after-commas +--procnames-start-lines +--space-after-cast +--space-after-for +--space-after-if +--space-after-while +--struct-brace-indentation 0 +--swallow-optional-blank-lines +--blank-lines-after-procedures +//--blank-lines-after-declarations +--break-before-boolean-operator +--comment-indentation 30 +--continue-at-parentheses +--comment-line-length 80 diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..ee948bc --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,3 @@ +(c) Pierre Gentile (p.gen.progs@gmail.com) + +License: GPLv2 diff --git a/INTERNALS.rst b/INTERNALS.rst new file mode 100644 index 0000000..2178de1 --- /dev/null +++ b/INTERNALS.rst @@ -0,0 +1,56 @@ +Words are read into two datastructures: + +To illustrate these datastructures, we will suppose the following input text:: + + a b c d e f g h + a b a d + f g h + + z + +The main datastructures are: + +- An array indexed by their order of appearance. + + This is not purely a string array, words are structures which contain the + following informations: + + - the display string which can be shorter than the original string; + - the original string; + - a flag indicating the this is the last word in a paragraph like + **h**, **d**, **h** and **z** if our example test; + - positional infomations: column start, column end end an number of + multibyes between the two. + + The following text will be put in the word array:: + + + last=1 last=1 last=1 last=1 + | | | | + +---+---+---+---+---+---+---+-v-+---+---+---+-v-+---+---+-v-+-v-+ + | a | b | c | d | e | f | g | h | a | b | a | d | f | g | h | z | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + 0 1 . . . 13 14 15 + +- A Ternary Search Treee (TST) which store their position in the array + and all their furure positions if their appear multiple times. + + In the TST tree, index lists are attached to the input words:: + + +---+---+----+ + a | 0 | 8 | 10 | + +---+---+----+ + + +---+---+ + b | 1 | 9 | + +---+---+ + + +---+ + c | 2 | + +---+ + + and so on. + + This TST is used when searching a word using the ``/`` command or when using + the ``-s`` commandline option. + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..0671f06 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,264 @@ +The GNU General Public License, Version 2, June 1991 (GPLv2) +============================================================ + +> Copyright (C) 1989, 1991 Free Software Foundation, Inc. +> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + + +Preamble +-------- + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to most +of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you can +do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a +fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer +you this license which gives you legal permission to copy, distribute and/or +modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced by +others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish +to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's free +use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + + +Terms And Conditions For Copying, Distribution And Modification +--------------------------------------------------------------- + +**0.** This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program or +work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included without +limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is not +restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's source code +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the Program +a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at +your option offer warranty protection in exchange for a fee. + +**2.** You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you also +meet all of these conditions: + +* **a)** You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + +* **b)** You must cause any work that you distribute or publish, that in whole + or in part contains or is derived from the Program or any part thereof, to + be licensed as a whole at no charge to all third parties under the terms of + this License. + +* **c)** If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the entire whole, +and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on the +Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +**3.** You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and 2 +above provided that you also do one of the following: + +* **a)** Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above on + a medium customarily used for software interchange; or, + +* **b)** Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + +* **c)** Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only for + noncommercial distribution and only if you received the program in object + code or executable form with such an offer, in accord with Subsection b + above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all the +source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code distributed +need not include anything that is normally distributed (in either source or +binary form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component itself +accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source code +from the same place counts as distribution of the source code, even though third +parties are not compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you do +not accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms and +conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +**7.** If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution of +the Program by all those who receive copies directly or indirectly through you, +then the only way you could satisfy both it and this License would be to refrain +entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and the +section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In such +case, this License incorporates the limitation as if written in the body of this +License. + +**9.** The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be similar +in spirit to the present version, but may differ in detail to address new +problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Program does not specify a version number of this License, you may choose any +version ever published by the Free Software Foundation. + +**10.** If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + + +No Warranty +----------- + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eca6a36 --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +# Some variables +CC = gcc +RM = rm +CURSES=ncurses + +TAG=`if git status >/dev/null 2>&1; then \ + echo "git "; \ +else \ + test -f version && cat version; \ +fi` + +VERSION=`if git status >/dev/null 2>&1; then \ + git log -n 1 --pretty=format:"%h"; \ +else \ + echo ""; \ +fi` + +DATE=`if git status >/dev/null 2>&1; then \ + echo ", build: "\`date +%x_%Z\`; \ +else \ + echo ", build: "\`date +%x_%H:%M_%Z\`; \ +fi` + +# Compilation and link phases options +CFLAGS = -c -g -O2 -Wall -Wextra +LFLAGS = -l$(CURSES) + +# The build target +OBJS = smenu.o +TARGET = smenu + +# The rules +all: $(TARGET) + +.c.o : + @echo "CC " $< + @$(CC) $(CFLAGS) -DVERSION=\""$(TAG)$(VERSION)$(DATE)"\" $< + +$(TARGET): $(OBJS) + @echo CCLD $< + @$(CC) -o $@ $(OBJS) $(LFLAGS) + +clean: + $(RM) -f $(OBJS) $(TARGET) smenu-*.tar.gz core + +strip: + strip $(TARGET) + +archive: + @if git status >/dev/null 2>&1; then \ + V=$(VERSION); \ + if git archive --prefix=smenu-$${V}/ -o smenu-$${V}.tar.gz $${V}; then \ + echo "smenu-$${V}.tar.gz written."; \ + fi \ + else \ + echo "This is not a git repository."; \ + fi diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..bdc841e --- /dev/null +++ b/README.rst @@ -0,0 +1,102 @@ +What is it? +=========== +**smenu** is a selection filter just like ``sed`` is an editing filter. + +This simple tool reads words from the standard input, presents them in +a cool interactive window after the current line on the terminal and writes +the selected word, if any, on the standard output. + +After having unsuccessfully searched the NET for what I wanted, I +decided to try to write my own. + +I have tried hard to made its usage as simple as possible. It should +work, even when using an old ``vt100`` terminal and is ``UTF-8`` aware. + +How to build? +============= +**smenu** can be built on every system where a working ``terminfo`` +developpement platform is available. This includes every Unix and Unix +like systems I am aware of. + +You may need to adjust the ``CURSES`` variable in the Makefile. On Linux, +by example, you need ``ncurses``. + +After that, a simple ``make`` should be sufficient to build the program. + +There is no installation procedure as all that is required to do is to +put the resulting binary and the man page in their traditional places. + +Some examples. +============== + +Linux example. +-------------- +This program should work on most Unix but if you are using Linux, +try to type the following line at a shell prompt (here: ``"$ "`` ): + +:: + + $ R=$(grep Vm /proc/$$/status \ + | IFS=$':\n' smenu -n20 -q -c -b -g -s /VmH) + $ echo $R + +Something like this should now be displayed with the program waiting +for commands: (numbers are mine, yours will be different) + +:: + + VmPeak¦ 23840 kB¦ + VmSize¦ 23836 kB¦ + VmLck ¦ 0 kB¦ + VmHWM ¦ 2936 kB¦ + VmRSS ¦ 2936 kB¦ + VmData¦ 1316 kB¦ + VmStk ¦ 136 kB¦ + VmExe ¦ 28 kB¦ + VmLib ¦ 3956 kB¦ + VmPTE ¦ 64 kB¦ + VmSwap¦ 0 kB¦ + +A cursor should be under ``"VmHWM "``. + +After having moved the cursor to ``" 136 kB"`` and ended the program +with ``<Enter>``, the shell variable R should contain: ``" 136 kB"``. + +.. raw:: pdf + + PageBreak + +Unix example. +------------- +The following command, which is Unix brand agnostic, should give you a +scrolling window if you have more than 10 accounts on your Unix with a +UID lower than 100: + +:: + + $ R=$(awk -F: '$3 < 100 {print $1,$3,$4,$NF}' /etc/passwd \ + | smenu -n10 -c) + $ echo $R + +On mine (``LANG`` and ``LC_ALL`` set to ``POSIX``) it displays: + +:: + + at 25 25 /bin/bash \ + sys 0 3 /usr/bin/ksh + + bin 1 1 /bin/bash | + daemon 2 2 /bin/bash | + ftp 40 49 /bin/bash | + games 12 100 /bin/bash | + lp 4 7 /bin/bash | + mail 8 12 /bin/false | + named 44 44 /bin/false | + ntp 74 108 /bin/false v + +Note the presence of a scrollbar. + +Interested? +----------- +Please read the included man page to learn more about this little program. + +On Linux, ``man ./smenu.1`` will do it. @@ -0,0 +1,4 @@ +# B: Bugs to fix, I: possible Improvements +# ========================================. +I improve the notion of input words (enable quotation). +I enable multi-lines messages @@ -0,0 +1,255 @@ +.TH smenu 1 "May 2015" "Version 0.9" +.SH NAME +smenu - filter that allows to interactively select a word from stdin +and outputs the selection to stdout. +.SH SYNOPSIS +smenu [\fB-h\fP] [\fB-n\fP \fIlines\fP] [\fB-t\fP [\fIcols\fP]] +[\fB-s\fP \fIpattern\fP] [\fB-m\fP \fImessage\fP] [\fB-w\fP] [\fB-d\fP] +[\fB-c\fP] [\fB-e\fP] [\fB-b\fP] [\fB-g\fP] [\fB-q\fP] +.SH DESCRIPTION +This small utility acts as a filter (read from stdin and write to +stdout). All the words taken from stdin are presented in a scrolling +window on the terminal with a selection cursor initially positioned on +the first word by default. +.P +If the \fBIFS\fP variable is set, each of its character (or multibyte +sequence) will be used to delimit the words when reading them. Default +delimiters are: \fISPACE\fP, \fI\\t\fP and \fI\\n\fP. +.P +Non printable characters in words that are not a delimiter are +converted to their traditional form (\fI\\n\fP for end-of-line, +\fI\\t\fP for tabulation...) by default. A single dot (\fI.\fP) is also +used as a placeholder otherwise. +.P +\fBWarning\fP, \fBUTF-8\fP encoded codepoints are quietly converted +into a dot (\fI.\fP) when the user locale is not \fBUTF-8\fP aware like +\fBPOSIX\fP or \fBC\fP by example. +.P +If a word is only containing spaces, then all of them are +converted into underscores (\fI_\fP) so that we can see them. +.P +.SS "Moving among words" +The cursor can then be moved in every directions by using the +traditional arrow keys or the \fIvi\fP direction keys (\fBh\fP, +\fBj\fP, \fBk\fP and \fBl\fP). \fBHOME\fP, \fBEND\fP, \fBPgDn\fP and +\fBPGUp\fP can also be used if available and have their traditional +meanings. +.SS "Searching for a word" +The \fB/\fP or \fB^F\fP (\fBCtrl-f\fP) can be used to initiate a +research by prefix among the words after the cursor. +.P +After that the cursor attribute is modified and all the characters +entered 7s after this change goes in a search buffer with the cursor +moving immediately to the next word matching this prefix. Any character +entered within 5s after that completes that buffer and resets the 5s +timer and possibly moves the cursor again. +.P +As soon as the timer expiates, the search mode is ended and the +cursor regains its initial appearance. +.P +The search buffer if persistent as long as the cursor is on a matching +word when a new research is initialized. +.br +If the beginning of the word under the cursor does not match the +previous search buffer, then the search buffer if erased. +.P +At any time in this mode you can move the cursor with the keys +described above. \fBESC\fP ends this mode immediately. +.P +The \fBSPACE\fP or \fBn\fP keys repeats the last research if the search +buffer is not empty. As in search mode, nothing happens if there is no +matching word after the cursor. +.P +Note that only the \fBSPACE\fP key can be used when the search mode is +active because the \fBn\fP character must be available if you want to +search a word containing this character. +.SS "Selection and Exit" +Hitting \fBq\fP exits without outputting anything, nothing is selected. +.P +By default, hitting \fBENTER\fP writes the selected word to stdout when +not in search mode. In search mode \fBENTER\fP ends this mode and do +nothing more. If you want to be able to select a word \fIeven\fP in +search mode, use the \fB-e\fP option to change this behavior. +.SS Help +A small help message can be displayed when hitting \fB?\fP. This display +will last for 10s or until a valid key or \fBESC\fP is pressed. +.SS Scrollbar +A scroll bar is displayed at the left of the scrolling window. Its +appearance is meant to be classical but it has some particularities: +.IP * 2 +The scroll bar is displayed only if all the words could not be +displayed on the terminal . +.IP * 2 +When the scrolling window has only one line, the scroll bar has only 3 +states: +.RS 2 +.IP - 2 +"\fBv\fP" when on all but the last line, indicating that you can go down +to see more. +.IP - 2 +"\fB^\fP" when on the last line. +.IP - 2 +"\fB|\fP" otherwise. +.RE +.IP * 2 +When there is more than 1 line to display, "\fB/\fP" means that the window +displays the first line, "\fB\\\fP" the last line. "\fB|\fP" is used to fill +the gap, see below the different possibles configurations. +.TS +l l l l l +l l l l l +l l l l. +\\ \\ ^ ^ \\ +| | | | / +/ v / v +.TE +.P +A "\fB+\fP" can also appear in the scroll bar in lieu of a "\fB|\fP", +giving the relative position of the cursor line in the bunch of input +words. +.SS "Terminal resizing" +The windows is redrawn is the terminal is resized. The redrawing is +actually done only 1s after the end of the resizing to avoid artefacts +on screen. The cursor will remain on the current selected word but may +be displayed on another place in the window. +.SS Unicode support +This utility is Unicode aware and should be able to display correctly +any Unicode character (even double-width ones) as long as the current +encoding is \fBUTF-8\fP (\fBUTF-8\fP in the output of the \fIlocale\fP +command). +.SH OPTIONS +.IP \fB-h\fP +Display a shot help message and exists. +.IP "\fB-n\fP \fIlines\fB" +Gives the maximum number of lines in the scrolling selection window. By +default five lines at most are displayed and the other ones, if +any, need you to scroll the window. +.IP "\fB-t\fP [\fIcolumns\fP]" +This option sets the tabulation mode and, if a number is specified, +limits the number of displayed columns to that number. +.IP "\fB-s\fP \fIpattern\fP" +Pre-Position the cursor to the specified pattern. \fIpattern\fP" can be: +.RS +.IP * 2 +A \fBnumber\fP giving the initial position of the cursor (counting from +0). If this number if greater than the number of words, the cursor will +be set on la last position. +.IP * 2 +The string \fBlast\fP meaning that we want the initial position to be +on the last word. +.IP * 2 +A string starting with a "\fB/\fP" indicating that we want the cursor +to be set on the first word matching the \fBprefix\fP string following +the "\fB/\fP" (\fB/Ca\fP will match \fBCancel\fP by example). +.PP +Every failure will no nothing resulting with the cursor set on the +first word. +.RE +.IP "\fB-m\fP \fImessage\fP" +Permits to display a message above the window. Beware, it will be +truncated to only being displayed on \fIone\fP line. +.IP "\fB-w\fP" +When \fB-t\fP is used, the default is to compact the columns so that +they use the less terminal width as possible. This option enlarges the +columns in order to cover the whole terminal width when a number of +columns is specified. +.P +Notice that the column's size is only calculated once when the +words are displayed for the first time. A terminal resize will not +alter this value. This choice permits a faster display. +.P +.RS +Note that if this mode each column has the same width. +.RE +.IP \fB-d\fP +Tells the program to clean up the display before quitting by removing +the selection window after use as if it were never displayed. The +terminal may have been scrolled up anyway if the previous window +display needed it. +.IP \fB-c\fP +Sets the column mode. In this mode the lines of words do not wrap when +the right border of the terminal is reached but only when a special +character is read. Some words will not be displayed without an +horizontal scrolling. +.RS +.P +If such a scrolling is needed, an horizontal scroll bar will be +displayed at the top of the window. +.P +In this mode, the width of each column is minimal to keep the maximum +information visible on the terminal. +.P +The line terminator is "\fI\\n\fR" by default is the shell variable +\fBIRS\fP is undefined. Otherwise its characters (or multibyte sequence) +will be used as a line terminator. Characters (or multibyte sequences) +in \fBIRS\fP are automatically added to the list of word delimiters. +.RE +.IP \fB-e\fP +Enables \fBENTER\fP to validate the selection even in search mode. +.IP \fB-b\fP +Replace all non-printable characters by a blank. +.IP \fB-g\fP +Replaces the blank after each words in normal tabular mode by a vertical +bar "\fB|\fP". Some users may find the output more readable like that. +.IP \fB-q\fP +Prevents the scrollbar display. Useful when all the input words can be +displayed without the need of scrolling. by default the scrollbar is +always displayed when there is more than one line. An absence of cursor +in it gives a visual indication that all the input words are there. +.SH NOTES +If tabulations (\fI\\t\fP) are embedded in the input, there is no way +to replace them with the original number of spaces. In this case use +an other filter (like \fIexpand\fR) to pre-process the data. +.SH EXAMPLES +.SS 1 +Simple Yes/No/Cancel request with "No" as default choice: +.P +.nf +In \fBbash\fP: \fBread R <<< $(echo "Yes No Cancel" \\ + | smenu -d -m "Please choose:" -s /N)\fP + + or \fBR=$(echo "Yes No Cancel" \\ + | smenu -d -m "Please choose:" -s /N)\fP + +In \fBksh\fP: \fBprint "Yes No Cancel" \\ + | smenu -d -m "Please choose:" -s /N \\ + | read R\fP +.fi +.SS 2 +Get a 3 columns report about VM statistics for the current process in +\fBbash\fP/\fBksh\fP on Linux: +.P +.nf +\fBR=$(grep Vm /proc/$$/status | expand | IFS=$'\\n' smenu -b -t3 -g -d)\fB +.P +.fi +.SS 3 +Create a one column selection window containing the list of the first +20 LVM physical volumes. At end, the selection window will be erased. +This example is written in \fBksh\fP). +.P +.nf +\fBpvs -a -o pv_name --noheadings \\ +| smenu -m "PV list" -n20 -t1 -d -s //dev/root \\ +| read R\fP +.fi +.P +The display will have a look similar to the following with the cursor +set on the word \fI/dev/root\fP: +.P +.nf +PV list +/ /dev/md126 +| /dev/md127 +| /dev/root <- cursor here +| /dev/sda2 +| /dev/sdb2 +| /dev/sdc1 +| /dev/sdc2 +\\ /dev/system/homevol +.fi +.SH BUGS +None that I am aware of. If you found one, please tell me. +.SH AUTHOR +\(co 2015 Pierre Gentile (p.gen.progs@gmail.com) +.SH SEE ALSO @@ -0,0 +1,3737 @@ +/* ################################################################### */ +/* Copyright 2015 - Pierre Gentile */ +/* */ +/* This Software is licensed under the GPL licensed Version 2, */ +/* please read http://www.gnu.org/copyleft/gpl.html */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* General Public License as published by the Free Software */ +/* Foundation; either version 2 of the License. */ +/* */ +/* This software is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. */ +/* ################################################################### */ + +#define CHARSCHUNK 8 +#define WORDSCHUNK 8 +#define COLSCHUNK 16 + +#define _XOPEN_SOURCE 600 +#include <termios.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <locale.h> +#include <langinfo.h> +#include <term.h> +#include <errno.h> +#include <wchar.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include "smenu.h" + +int bar_color; /* scrollbar color */ +int count = 0; /* number of words read from stdin */ +int current; /* index the current selection * + * (under the cursor) */ +int new_current; /* final current position, (used in * + * search function) */ +int *line_nb_of_word_a; /* array containig the line number * + * (from 0) of each word read */ +int *first_word_in_line_a; /* array containing the index of * + * the first word of each lines */ +int search_mode = 0; /* 1 if in search mode else 0 */ +int help_mode = 0; /* 1 if help is display else 0 */ + +int (*my_isprint) (int); + +static int delims_cmp(const void *a, const void *b); + +/* UTF-8 usefull symbols */ +/* """"""""""""""""""""" */ +char *sbar_broken_line = "\xc2\xa6"; /* broken_bar */ +char *sbar_arr_left = "\xe2\x86\x90"; /* leftwards_arrow */ +char |