summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpgen <p.gen.progs@gmail.com>2018-03-24 11:53:51 +0100
committerpgen <p.gen.progs@gmail.com>2018-03-25 23:22:31 +0200
commite44ef2fe362ec05102a417349488b15f73db3f1e (patch)
tree962b319a7e15f8cdbc665b844a23c8473ea4a581
parentffab5ac2e1a8c41be6cf8794d2c5948c4002ea73 (diff)
Fix and rewrite parts of the numbering code
Summary: - Added the -U option - Added the -D option to the manages -N/-U and -F sub-options - Fixed and simplified the -N and -F options - Cleaned code - Fixed and improved the manual - Fixed various small bugs
-rwxr-xr-xexamples/lvm_menu/menu.sh2
-rw-r--r--smenu.1192
-rw-r--r--smenu.c768
3 files changed, 549 insertions, 413 deletions
diff --git a/examples/lvm_menu/menu.sh b/examples/lvm_menu/menu.sh
index e3854bb..b1dd724 100755
--- a/examples/lvm_menu/menu.sh
+++ b/examples/lvm_menu/menu.sh
@@ -56,7 +56,7 @@ fi
REP=$(../../smenu "$TITLE" \
-s /Exit \
-q -d -M -n 30 -c -w \
- -N "Exit menu" e:r \
+ -U "Exit menu" \
-a da:3,b \
-e '^#' -E '/(^#)+(.*)$/ \2/v' \
-1 'Exit' 2,r \
diff --git a/smenu.1 b/smenu.1
index 32eccbb..fe3e30a 100644
--- a/smenu.1
+++ b/smenu.1
@@ -9,7 +9,8 @@ and outputs the selection to stdout.
[\fB-s\fP \fIpattern\fP] [\fB-m\fP \fImessage\fP] [\fB-w\fP] \\
[\fB-d\fP] [\fB-M\fP] [\fB-c\fP] [\fB-l\fP] [\fB-r\fP] [\fB-b\fP] \\
[\fB-a\fP (i|e|c|b|s|t|sf|st|da):\fIATTR\fP]... \\
- [\fB-i\fP \fIregex\fP] [\fB-e\fP \fIregex\fP] [\fB-C\fP \
+ [\fB-i\fP \fIregex\fP] [\fB-e\fP \fIregex\fP] \\
+ [\fB-C\fP \
[\fIa\fP|\fIs\fP|\fIi\fP|\fIr\fP|\fId\fP|\fIe\fP]<col selectors>] \\
[\fB-R\fP \
[\fIa\fP|\fIs\fP|\fIi\fP|\fIr\fP|\fId\fP|\fIe\fP]<row selectors>] \\
@@ -17,9 +18,8 @@ and outputs the selection to stdout.
[\fB-I\fP \fI/regex/string/\fP[\fIg\fP][\fIv\fP][\fIs\fP][\fIi\fP]] \\
[\fB-E\fP \fI/regex/string/\fP[\fIg\fP][\fIv\fP][\fIs\fP][\fIi\fP]] \\
[\fB-A\fP \fIregex\fP] [\fB-Z\fP \fIregex\fP] \\
- [\fB-N\fP \fIregex\fP \\
- [\fB-F\fP \fItype\fP \\
- [\fB-D\fP [\fIFargument\fP]...] \\
+ [\fB-N\fP \fIregex\fP] [\fB-U\fP \fIregex\fP] [\fB-F\fP] \
+[\fB-D\fP \fIsub-option\fP...] \\
[\fB-1\fP \fIregex\fP [\fIATTR\fP]] \
[\fB-2\fP \fIregex\fP [\fIATTR\fP]] ... \
[\fB-5\fP \fIregex\fP [\fIATTR\fP]] \\
@@ -30,12 +30,14 @@ and outputs the selection to stdout.
<col selectors> ::= \fIcol1\fP[-\fIcol2\fP],...|\fI<RE>\fP,...
<row selectors> ::= \fIcol1\fP[-\fIcol2\fP],...|\fI<RE>\fP,...
- <argument> ::= [l|r:<char>]|[a:l|r]|[p:i|a|[e:m|r]|[w:<num>]
- |[o:<num>]|[s:<num>]|[d:<char>]
+ <sub-option> ::= [l|r:<char>]|[a:left|right]|[p:included|all|
+ [w:<num>]|[f:yes|no]|[o:<num>]|[n:<num>]|
+ [i:<num>]
<ATTR> ::= [fg][/bg][,style]
- <RE> ::= \fB<char>\fIregex\fB<char>\fP
+ <RE> ::= \fB<char>\fIregex\fB<char>\fR
<col/row selectors> and <RE> can be freely mixed.
+ The parameters of -a and -D must be delimited by blanks.
.fi
.SH DESCRIPTION
This small utility acts as a filter when no input file is given
@@ -99,6 +101,17 @@ keyboard arrow keys (\fB\(<-\fP,\fB\(da\fP,\fB\(ua\fP,\fB\(->\fP)
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.
+
+If the \fB-N\fP, \fB-U\fP or \fB-F\fP are used then it is possible to
+directly access a word by entering its number.
+The numbering created using these option is done \fBbefore\fP any words
+substitution done using \fB-S\fP, \fB-I\fP or \fB-E\fP.
+
+Using a combination of these options, it is easy to control which words
+will be numbered by adding a special symbol in it before using smenu and
+removing it (substituted by nothing) afterward using \fB-I\fP by example.
+
+\fB-E\fP gives another way to do that, see below or more.
.SS "Searching for a word"
The key \fB/\fP or the key combination \fB^F\fP (\fBCTRL+f\fP) can be
used to initiate a search by prefix among the words (possibly altered
@@ -399,6 +412,7 @@ This mode is the same as column mode but without any column alignment.
Enables \fBENTER\fP to validate the selection even in search mode.
.IP \fB-b\fP
Replaces all non-printable characters by a blank.
+If this results in a blank word, it will be potentially deleted.
.IP "\fB-a \fIPREFIX:ATTR\fP [\fIPREFIX:ATTR\fP...]"
Sets the display attributes of the elements displayed and the cursor.
@@ -590,11 +604,11 @@ The same trick with \fB-L\fP can also be used.
.RS
\fI\\u\fP sequences can also be used in the regexp after \fB-Z\fP.
.RE
-.IP "\fB-N\fP [\fIparameters\fP]"
+.IP "\fB-N\fP [\fIregex\fP]"
This option allows to number the selectable words matching a specific
regular expression.
-These numbers are numbered from 1 and provides a direct access to
-the words.
+These numbers are numbered starting from 1 and provides a direct access
+to the words.
To use this functionality, the user must enter the number which
corresponds to the desired entry digit per digit.
@@ -605,48 +619,111 @@ will start a new number.
If the number does not exists, then the cursor is restored to it's
initial position.
-These optional parameters must respect the format \fBx\fP:\fBy\fP where
-\fBx\fP can be:
+The sub-options of the \fB-D\fP option described below can change the
+way \fB-N\fP sets and formats the numbers.
+
+This option can be used more than once with cummulative effects.
+
+\fB-N\fP, \fB-U\fP and \fB-F\fP can be mixed.
+.IP "\fB-U\fP [\fIregex\fP]"
+This option allows to un-number words.
+If placed after a previous \fB-N\fP, it can be used to remove the
+numbering of selected words.
+If placed before, the word which doesn't match its regular expression
+will be numbered by default.
+
+This mechanism is similar to to the inclusion/exclusion of words by
+\fB-i\fP and \fB-e\fP.
+
+This option can be used more than once with cummulative effects.
+
+\fB-U\fP, \fB-N\fP and \fB-F\fP can be mixed.
+.IP "\fB-F\fP"
+This option is similar to \fB-N\fP but does not generate a continuous
+flow of numbers but extracts them from the word itself.
+
+With this option you can take full control of the numbering of the
+displayed word.
+Note that the numbering does not need to be ordered.
-- '\f(CBl\fP'
+The resulting word after the extraction of the number must be non empty.
+
+Some sub-option are required, see the \fB-D\fP option described below.
+
+\fBNotice\fP that for this option to work correctly, all the embedded
+numbers must have the same number of digits.
+To get that, a preprocessing may be necessary on the words before using
+this program.
+
+\fB-F\fP, \fB-N\fP and \fB-U\fP can be mixed.
+.IP "\fB-D\fP [\fIparameters\fP]"
+This option allows to change the default behaviour or the \fB-N\fP,
+\fB-U\fP and \fB-F\fP options.
+
+Its optional parameters are called sub-options and must respect the
+format \fBx\fP:\fBy\fP where \fBx\fP can be:
+
+- '\f(CBl\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
where \fBy\fP is the UTF-8 character (in native or \fI\\u\fP form)
-to print before the number.
+to print before the number. The default is a single space.
-- '\f(CBr\fP'
+- '\f(CBr\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
where \fBy\fP is the UTF-8 character (in native or \fI\\u\fP form)
-to print after the number.
+to print after the number. The default is \f(CB)\fP.
-- '\f(CBa\fP'
+- '\f(CBa\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
where \fBy\fP is '\f(CBleft\fP' (or one of its prefixes) if the number
must be \fIleft\fP aligned, or '\f(CBright\fP' (or one of its prefixes)
-if it must be \fIright\fP aligned.
-
-- '\f(CBp\fP'
-where \fBy\fP is '\f(CBincluded\fP' (or one of its prefixes)
-or '\f(CBall\fP' (or one of its prefixes) for the initial padding of
-the non numbered words. '\f(CBincluded\fP' means that only
-\fIincluded\fP word will be padded while '\f(CBall\fP' means pad
-\fIall\fP words.
-
-- '\f(CBe\fP'
-where \fBy\fP is '\f(CBmatch\fP' (or one of its prefixes) if the words
-must \fImatch\fP the regular expression or '\f(CBinvert\fP' (or one of
-its prefixes) if they must \fBNOT\fP match it.
-
-- '\f(CBw\fP'
-where \fBy\fP is the width of the number between 1 and 5 included.
+if it must be \fIright\fP aligned. The default is \f(CBright\fP.
+
+- '\f(CBp\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
+where \fBy\fP is '\f(CBincluded\fP' (or one of its prefixes)
+or '\f(CBall\fP' (or one of its prefixes) for the initial \fIp\fPadding of
+the non numbered words. '\f(CBincluded\fP' means that only \fIincluded\fP
+word will be padded while '\f(CBall\fP' means pad \fIall\fP words. The
+default is \f(CBall\fP.
+
+- '\f(CBw\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
+where \fBy\fP is the \fIw\fPidth of the number between 1 and 5 included.
+
+- '\f(CBf\fP' (\fB-F\fP, \fB-N\fP and \fB-U\fP options)
+.br
+where \fBy\fP controls if the numbering must \fIf\fPollow the last
+extracted number (defaults to \f(CByes\fP) or if it must remain
+independant.
+
+- '\f(CBo\fP' (\fB-F\fP option)
+.br
+where \fBy\fP is the \fIo\fPffset of the first multibyte character of
+the number to extract from the word (defaults to \f(CB0\fP).
+
+- '\f(CBn\fP' (\fB-F\fP option)
+.br
+where \fBy\fP is the \fIn\fPumber of multibyte characters to extract
+from the word starting at the offset given by the \f(CBo\fP sub-option.
+
+- '\f(CBi\fP' (\fB-F\fP option)
+.br
+where \fBy\fP is number of multibyte characters to \fIi\fPgnore after
+the extracted number
Example: \f(CWr:\\> l:\\< a:l\fP
-To number all words with the default parameters, use the syntax:
-"\f(CW-N .\fP"
-which is a shortcut for: "\f(CW-N . l:' ' r:')' a:r p:a e:m\fP"
+To number all words with the default parameters, use the
+syntax: "\f(CW-N .\fP" which is a shortcut for:
+"\f(CW-N . l:' ' r:')' a:r p:a\fP"
-The \fIpadding\fP directive specifies whether spaces must also be added
-in front of excluded words or not to improve compactness.
+The \fIpadding\fP sub-option specifies whether spaces must also be
+added in front of excluded words or not to improve compactness.
-When the \f(CBw\fP optional parameter is not given the width of the
-numbers is determined automatically.
+When the \f(CBw\fP sub-option is not given the width of the numbers is
+determined automatically but if \fB-F\fP is set and the value of the
+\f(CBn\fP sub-option is given then this value is used.
.IP "\fB-1\fP ... \fB-5\fP \fIregex\fP [\fIATTR\fP]"
Allows to give up to 5 classes of words specified by regular expressions
a special display color.
@@ -858,11 +935,11 @@ Imagine a file named \fBsample.mnu\fP with the following content:
.nf
\f(CR--8<---------------------------------
-[1] "First Entry" [3] "Third entry"
-[2] "Second entry" [4] "Fourth entry"
-@@@ @@@ [5] "Fifth entry"
+"1 First Entry" "3 Third entry"
+"2 Second entry" "4 Fourth entry"
+@@@ "5 Fifth entry"
@@@
-[Quit] "Exit menu"
+"0 Exit menu"
--8<---------------------------------
\fP
.fi
@@ -870,25 +947,26 @@ Imagine a file named \fBsample.mnu\fP with the following content:
Then this quite esoteric command will render it (centered on the screen) as:
.nf
-\f(CR+--------------------------------+
-|Test menu |
-|1 First Entry 3 Third entry |
-|2 Second entry 4 Fourth entry|
-| 5 Fifth entry |
-| |
-|Quit Exit menu |
-+--------------------------------+
+\f(CR+----------------------------------+
+| Test menu |
+| |
+| 1) First Entry 3) Third entry |
+| 2) Second entry 4) Fourth entry |
+| 5) Fifth entry |
+| |
+| 0) Exit menu |
++----------------------------------+
\fP
.fi
with the cursor on \fIQuit\fP and only the numbers and "Quit" selectable.
-\f(CBR=$(smenu -q -d -s/Q -M -n 30 -c \\
- -e "@+" -E '/@+//' \\
- -i '\\[ *[^ ]+ *\\]' -I '/[][ ]//g' \\
- -m "Test menu" < sample.mnu)\fP
+\f(CBR=$(smenu R=$(./smenu -q -d -s/Exit -M -n 30 -c \\
+ -e "@+" -E '/@+/ /' \\
+ -F -D n:1 i:1 \\
+ -m "Test menu"$'\n' < sample.mnu)
-The selected number or string will be available in \f(CBR\fP
+The selected entry will be available in \f(CBR\fP
Try to understand it as an exercise.
.SH ENVIRONMENT
diff --git a/smenu.c b/smenu.c
index e1392c1..b41e42b 100644
--- a/smenu.c
+++ b/smenu.c
@@ -349,12 +349,13 @@ enum filter_types
EXCLUDE_FILTER
};
+/* Used by the -N -F and -D options */
+/* """""""""""""""""""""""""""""""" */
enum daccess_types
{
- DACCESS_NONE = 0,
- DACCESS_AUTO = 1,
- DACCESS_POS = 2,
- DACCESS_DELIM = 4
+ DA_TYPE_NONE = 0, /* must be 0 (boolean value) */
+ DA_TYPE_AUTO = 1,
+ DA_TYPE_POS = 2
};
/* Used when managing the -R option */
@@ -619,16 +620,15 @@ struct daccess_s
int type; /* 1: auto, 2: delimiter, 4: positional */
char * left; /* character to put before the direct access selector */
char * right; /* character to put after the direct access selector */
- char * delim; /* field delimiter */
char alignment; /* l: left; r: right */
char padding; /* a: all; i: only included words are padded */
- char expression; /* m: match; r: reverse match the regular expression */
- char remove; /* y: remove from word, n: don't */
int length; /* selector size (5 max) */
- int start_off; /* offset to the start of the selector */
- int end_off; /* offset to the end of the selector */
- int width; /* max width of the selector */
- int skip; /* Number of multibytes to skip after the number */
+ int flength; /* 0 or length + 3 (full prefix lengh */
+ int offset; /* offset to the start of the selector */
+ int size; /* size in bytes of the selector to extract */
+ int ignore; /* number of multibytes to ignore after the number */
+ int follow; /* y: the numbering follows the last nuber set */
+ int def_number; /* 1: the numbering is on by default 0: it is not */
};
/* **************** */
@@ -779,7 +779,9 @@ short_usage(void)
fprintf(stderr, " [-S /regex/repl/[g][v][s][i]] ");
fprintf(stderr, "[-I /regex/repl/[g][v][s][i]] \\\n");
fprintf(stderr, " [-E /regex/repl/[g][v][s][i]] ");
- fprintf(stderr, "[-A regex] [-Z regex] [-N regex [arg]...] \\\n");
+ fprintf(stderr, "[-A regex] [-Z regex] \\\n");
+ fprintf(stderr, " [-N regex] [-U regex] [-F] [-D arg...] ");
+ fprintf(stderr, " \\\n");
fprintf(stderr, " [-1 regex [attr]] [-2 regex [attr]]... ");
fprintf(stderr, "[-5 regex [attr]] [-g] [-q] \\\n");
fprintf(stderr, " [-W bytes] [-L bytes] [-T [separator]] ");
@@ -789,13 +791,15 @@ short_usage(void)
fprintf(stderr, " <col selectors> ::= col1[-col2]...|<RE>...\n");
fprintf(stderr, " <row selectors> ::= row1[-row2]...|<RE>...\n");
fprintf(stderr, " <prefix> ::= i|e|c|b|s|t|sf|st|da\n");
- fprintf(stderr, " <arg> ::= [l|r:<char>]|[a:l|r]|[p:i|a|");
- fprintf(stderr, "[e:m|i]|[w:<size>]\n");
- fprintf(stderr, " (ex: l:'(' e:r)\n");
+ fprintf(stderr, " <arg> ::= [l|r:<char>]|[a:l|r]|[p:i|a]|");
+ fprintf(stderr, "[w:<size>]|\n");
+ fprintf(stderr, " [f:y|n]|[o:<num>]|[n:<num>]|");
+ fprintf(stderr, "[i:<num>]\n");
+ fprintf(stderr, " Ex: l:'(' a:l\n");
fprintf(stderr, " <attr> ::= [fg][/bg][,style] \n");
- fprintf(stderr, " (ex: 7/4,bu)\n");
+ fprintf(stderr, " Ex: 7/4,bu\n");
fprintf(stderr, " <RE> ::= <char>regex<char> \n");
- fprintf(stderr, " (ex: /regex/ or :regex:)\n\n");
+ fprintf(stderr, " Ex: /regex/ or :regex:\n\n");
fprintf(stderr, " <col/row selectors> and <RE> can be freely mixed ");
fprintf(stderr, "when used\n");
fprintf(stderr, " with -C and -R (ex: 2,/x/,4-5).\n");
@@ -866,8 +870,15 @@ usage(void)
"-Z forces a class of words to be the latest of the line they "
"appear in.\n");
fprintf(stderr,
- "-N numbers and provides a direct access to words matching (or not) "
- "a specific regex.\n");
+ "-N/-U numbers/un-numbers and provides a direct access to words "
+ "matching\n");
+ fprintf(stderr, " (or not) a specific regex.\n");
+ fprintf(stderr,
+ "-F numbers and provides a direct access to words by extracting the "
+ "number\n");
+ fprintf(stderr, " from the words.\n");
+ fprintf(stderr,
+ "-D sets sub-options to modify the behaviour of -N, -U and -F.\n");
fprintf(stderr,
"-1,-2,...,-5 gives specific colors to up to 5 classes of "
"selectable words.\n");
@@ -887,7 +898,7 @@ usage(void)
fprintf(stderr, "\nNavigation keys are:\n");
fprintf(stderr, " - Left/Down/Up/Right arrows or h/j/k/l.\n");
fprintf(stderr, " - Home/End.\n");
- fprintf(stderr, " - Numbers if some words are numbered (-N).\n");
+ fprintf(stderr, " - Numbers if some words are numbered (-N/-U/-F).\n");
fprintf(stderr, " - SPACE to search for the next match of a previously\n");
fprintf(stderr, " entered search prefix if any, see below.\n\n");
fprintf(stderr, "Other useful keys are:\n");
@@ -4450,7 +4461,7 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
/* prints the leading spaces */
/* """"""""""""""""""""""""" */
tputs(TPARM1(exit_attribute_mode), 1, outch);
- printf("%.*s", daccess.length + 3, tmp_word);
+ printf("%.*s", daccess.flength, tmp_word);
}
/* Set the search cursor attribute */
@@ -4470,17 +4481,13 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
/* Print and overwrite the beginning of the word with the search */
/* buffer content if it is not empty */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (daccess.length > 0)
- tputs(tmp_word + daccess.length + 3, 1, outch);
- else
- tputs(tmp_word, 1, outch);
+ tputs(tmp_word + daccess.flength, 1, outch);
if (buffer[0] != '\0')
{
int i = 0;
int buf_width;
- int total_daccess_sel_len;
/* Calculate the space taken by the buffer on screen */
/* """"""""""""""""""""""""""""""""""""""""""""""""" */
@@ -4488,16 +4495,9 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
mbstowcs(NULL, buffer, 0));
free(w);
- /* Size of the direct access selector to skip to reach the word */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (daccess.length > 0)
- total_daccess_sel_len = daccess.length + 3;
- else
- total_daccess_sel_len = 0;
-
/* Put the cursor at the beginning of the word */
/* """"""""""""""""""""""""""""""""""""""""""" */
- for (i = 0; i < e - s + 1 - total_daccess_sel_len; i++)
+ for (i = 0; i < e - s + 1 - daccess.flength; i++)
tputs(TPARM1(cursor_left), 1, outch);
/* Set the buffer display attribute */
@@ -4512,17 +4512,14 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
/* Put back the cursor after the word */
/* """""""""""""""""""""""""""""""""" */
- for (i = 0; i < e - s - buf_width + 1 - total_daccess_sel_len; i++)
+ for (i = 0; i < e - s - buf_width + 1 - daccess.flength; i++)
tputs(TPARM1(cursor_right), 1, outch);
}
}
else
{
- int offset = 0;
if (daccess.length > 0)
{
- offset = daccess.length + 3;
-
/* If this word is not numbered, reset the display */
/* attributes before printing the leading spaces. */
/* """"""""""""""""""""""""""""""""""""""""""""""" */
@@ -4531,7 +4528,7 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
/* Print the non significant part of the word */
/* """""""""""""""""""""""""""""""""""""""""" */
tputs(TPARM1(exit_attribute_mode), 1, outch);
- printf("%.*s", offset - 1, word_a[pos].str);
+ printf("%.*s", daccess.flength - 1, word_a[pos].str);
tputs(TPARM1(exit_attribute_mode), 1, outch);
fputc(' ', stdout);
}
@@ -4601,7 +4598,7 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
}
mb_strprefix(tmp_word, word_a[pos].str, (int)word_a[pos].mb - 1, &p);
- tputs(tmp_word + offset, 1, outch);
+ tputs(tmp_word + daccess.flength, 1, outch);
}
tputs(TPARM1(exit_attribute_mode), 1, outch);
}
@@ -4641,7 +4638,7 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
/* """"""""""""""""""""""""""""""""""""""""""""""""""""" */
tputs(TPARM1(exit_attribute_mode), 1, outch);
if (daccess.padding == 'a')
- for (i = 0; i < daccess.length + 3; i++)
+ for (i = 0; i < daccess.flength; i++)
fputc(' ', stdout);
}
@@ -4694,7 +4691,7 @@ disp_word(word_t * word_a, int pos, int search_mode, char * buffer,
if ((daccess.length > 0 && daccess.padding == 'a')
|| word_a[pos].is_numbered)
- tputs(tmp_word + daccess.length + 3, 1, outch);
+ tputs(tmp_word + daccess.flength, 1, outch);
else
tputs(tmp_word, 1, outch);
@@ -5133,19 +5130,11 @@ search_next(tst_node_t * tst, word_t * word_a, char * search_buf,
{
wchar_t * w;
int found = 0;
- int total_daccess_sel_len;
-
- /* Size of the direct access selector to skip to reach the word */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (daccess.length < 0)
- total_daccess_sel_len = 0;
- else
- total_daccess_sel_len = daccess.length + 3;
/* Consider a word under the cursor found if it matches the search prefix. */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
if (!after_only)
- if (memcmp(word_a[current].str + total_daccess_sel_len, search_buf,
+ if (memcmp(word_a[current].str + daccess.flength, search_buf,
strlen(search_buf))
== 0)
return 1;
@@ -5597,11 +5586,16 @@ main(int argc, char * argv[])
int index; /* generic counter */
- int daccess_index = 1;
- char * daccess_locator_type = NULL;
- char * daccess_pattern = NULL;
- regex_t daccess_pattern_re; /* variable to store the compiled *
- * direct access pattern (-N) RE */
+ int daccess_index = 1;
+ char * daccess_locator_type = NULL;
+
+ char * daccess_np = NULL;
+ regex_t daccess_np_re; /* variable to store the compiled *
+ * direct access pattern (-N) RE */
+
+ char * daccess_up = NULL;
+ regex_t daccess_up_re; /* variable to store the compiled *
+ * direct access pattern (-U) RE */
char * include_pattern = NULL;
char * exclude_pattern = NULL;
@@ -5896,21 +5890,24 @@ main(int argc, char * argv[])
timeout.remain = 0;
timeout.reached = 0;
- daccess.type = DACCESS_NONE;
+ daccess.type = DA_TYPE_NONE;
daccess.left = " ";
daccess.right = ")";
daccess.alignment = 'r';
daccess.padding = 'a';
- daccess.expression = 'm';
daccess.length = -2;
- daccess.width = 0;
- daccess.skip = 0;
+ daccess.flength = 0;
+ daccess.offset = 0;
+ daccess.size = 0;
+ daccess.ignore = 0;
+ daccess.follow = 'y';
+ daccess.def_number = -1;
/* Command line options analysis */
/* """"""""""""""""""""""""""""" */
while ((opt = egetopt(argc, argv,
"Vf:h?X:x:qdMba:i:e:S:I:E:A:Z:1:2:3:4:5:C:R:"
- "kclwrgn:t%m:s:W:L:T%P%pN:F:"))
+ "kclwrgn:t%m:s:W:L:T%P%pN:U:FD:"))
!= -1)
{
switch (opt)
@@ -6227,6 +6224,9 @@ main(int argc, char * argv[])
optind--;
+ if (*argv[optind] == '-')
+ TELL("A blank is required before the first sub-option -- ");
+
/* Parse the arguments arguments */
/* """"""""""""""""""""""""""""" */
while (argv[optind] && *argv[optind] != '-')
@@ -6382,183 +6382,165 @@ main(int argc, char * argv[])
toggle.autotag = 1;
break;
- case 'N':
- {
- int pos;
- wchar_t * w;
- int n;
-
- if (daccess_pattern == NULL)
- daccess_pattern = xstrdup(optarg);
- else
- TELL("Option already given -- ");
+ case 'D':
+ if (optarg && *optarg != '-')
+ {
+ int pos;
+ wchar_t * w;
+ int n;
- daccess.type |= DACCESS_AUTO; /* auto */
+ /* Parse optional additional arguments */
+ /* """"""""""""""""""""""""""""""""""" */
+ optind--;
- /* Parse optional additional arguments */
- /* """"""""""""""""""""""""""""""""""" */
- while (argv[optind] && *argv[optind] != '-')
- {
- if (argv[optind][1] != ':')
- TELL("Bad format -- ");
+ if (*argv[optind] == '-')
+ TELL("A blank is required before the first sub-option -- ");
- switch (*(argv[optind]))
+ while (argv[optind] && *argv[optind] != '-')
{
- case 'l': /* left char */
- daccess.left = strdup(argv[optind] + 2);
- mb_interpret(daccess.left, &langinfo);
+ if (argv[optind][1] != ':')
+ TELL("Bad format -- ");
- if (mb_strlen(daccess.left) != 1)
- TELL("Too many characters after l: -- ");
+ switch (*(argv[optind]))
+ {
+ case 'l': /* left char */
+ daccess.left = strdup(argv[optind] + 2);
+ mb_interpret(daccess.left, &langinfo);
- n = wcswidth((w = mb_strtowcs(daccess.left)), 1);
- free(w);
+ if (mb_strlen(daccess.left) != 1)
+ TELL("Too many characters after l: -- ");
- if (n > 1)
- TELL("A multi columns character is not allowed after l: -- ");
- break;
+ n = wcswidth((w = mb_strtowcs(daccess.left)), 1);
+ free(w);
- case 'r': /* right char */
- daccess.right = strdup(argv[optind] + 2);
- mb_interpret(daccess.right, &langinfo);
+ if (n > 1)
+ TELL("A multi columns character is not allowed after l: -- ");
+ break;
- if (mb_strlen(daccess.right) != 1)
- TELL("Too many characters after r: -- ");
+ case 'r': /* right char */
+ daccess.right = strdup(argv[optind] + 2);
+ mb_interpret(daccess.right, &langinfo);
- n = wcswidth((w = mb_strtowcs(daccess.right)), 1);
- free(w);
+ if (mb_strlen(daccess.right) != 1)
+ TELL("Too many characters after r: -- ");
- if (n > 1)
- TELL("A multi columns character is not allowed after r: -- ");
- break;
+ n = wcswidth((w = mb_strtowcs(daccess.right)), 1);
+ free(w);
- case 'a': /* alignment */
- if (strprefix("left", argv[optind] + 2))
- daccess.alignment = 'l';
- else if (strprefix("right", argv[optind] + 2))
- daccess.alignment = 'r';
- else
- TELL("Bad format -- ");
- break;
+ if (n > 1)
+ TELL("A multi columns character is not allowed after r: -- ");
+ break;
- case 'p': /* padding */
- if (strprefix("all", argv[optind] + 2))
- daccess.padding = 'a';
- else if (strprefix("included", argv[optind] + 2))
- daccess.padding = 'i';
- else
- TELL("Bad format -- ");
- break;
+ case 'a': /* alignment */
+ if (strprefix("left", argv[optind] + 2))
+ daccess.alignment = 'l';
+ else if (strprefix("right", argv[optind] + 2))
+ daccess.alignment = 'r';
+ else
+ TELL("Bad format -- ");
+ break;
- case 'e': /* expression */
- if (strprefix("match", argv[optind] + 2))
- daccess.expression = 'm';
- else if (strprefix("invert", argv[optind] + 2))
- daccess.expression = 'i';
- else
- TELL("Bad format -- ");
- break;
+ case 'p': /* padding */
+ if (strprefix("all", argv[optind] + 2))
+ daccess.padding = 'a';
+ else if (strprefix("included", argv[optind] + 2))
+ daccess.padding = 'i';
+ else
+ TELL("Bad format -- ");
+ break;
- case 'w': /* width */
- if (sscanf(argv[optind] + 2, "%d%n", &daccess.length, &pos) != 1)
- TELL("Bad format -- ");
- if (argv[optind][pos + 2] != '\0')
- TELL("Bad format -- ");
- break;
+ case 'w': /* width */
+ if (sscanf(argv[optind] + 2, "%d%n", &daccess.length, &pos)
+ != 1)
+ TELL("Bad format -- ");
+ if (argv[optind][pos + 2] != '\0')
+ TELL("Bad format -- ");
+ if (daccess.length <= 0 || daccess.length > 5)
+ TELL("w suboption must be between 1 and 5 -- ");
+ break;
- default:
- TELL("Bad format -- ");
- }
+ case 'o': /* start offset */
+ if (sscanf(argv[optind] + 2, "%d%n", &daccess.offset, &pos)
+ != 1)
+ TELL("Bad format -- ");
+ if (argv[optind][pos + 2] != '\0')
+ TELL("Bad format -- ");
+ break;
- if (daccess.length <= 0 || daccess.length > 5)
- daccess.length = -2; /* special value -> auto */
+ case 'n': /* numbor of digits to extract */
+ if (sscanf(argv[optind] + 2, "%d%n", &daccess.size, &pos) != 1)
+ TELL("Bad format -- ");
+ if (argv[optind][pos + 2] != '\0')
+ TELL("Bad format -- ");
+ if (daccess.size <= 0 || daccess.size > 5)
+ TELL("n suboption must be between 1 and 5 -- ");
+ break;
- optind++;
- }
- }
+ case 'i': /* Number of multibytes to ignore after the selector to
+ extract */
+ if (sscanf(argv[optind] + 2, "%d%n", &daccess.ignore, &pos)
+ != 1)
+ TELL("Bad format -- ");
+ if (argv[optind][pos + 2] != '\0')
+ TELL("Bad format -- ");
+ break;
- break;
+ case 'f': /* follow */
+ if (strprefix("yes", argv[optind] + 2))
+ daccess.follow = 'y';
+ else if (strprefix("no", argv[optind] + 2))
+ daccess.follow = 'n';
+ else
+ TELL("Bad format -- ");
+ break;
- case 'F':
- {
- int pos;
- wchar_t * w;
- int n;
+ default:
+ TELL("Bad format -- ");
+ }
- if (daccess_locator_type == NULL)
- daccess_locator_type = xstrdup(optarg);
- else
- TELL("Option already given -- ");
+ if (daccess.length <= 0 || daccess.length > 5)
+ daccess.length = -2; /* special value -> auto */
- if (strprefix("delimiter", daccess_locator_type))
- daccess.type |= DACCESS_DELIM;
- else if (strprefix("positional", daccess_locator_type))
- daccess.type |= DACCESS_POS;
+ optind++;
+ }
+ }
else
- TELL("Bad locator type -- ");
-
- /* Parse optional additional arguments */
- /* """"""""""""""""""""""""""""""""""" */
- while (argv[optind] && *argv[optind] != '-')
- {
- if (argv[optind][1] != ':')
- TELL("Bad format -- ");
-
- switch (*(argv[optind]))
- {
- case 'd': /* delimiter */
- daccess.delim = strdup(argv[optind] + 2);
- mb_interpret(daccess.delim, &langinfo);
+ TELL("Option requires an argument -- ");
- if (mb_strlen(daccess.delim) != 1)
- TELL("Too many characters after d: -- ");
+ break;
- n = wcswidth((w = mb_strtowcs(daccess.delim)), 1);
- free(w);
- break;
+ case 'N':
+ if (daccess_np == NULL)
+ {
+ daccess_np = concat("(", optarg, ")", NULL);
+ daccess.type |= DA_TYPE_AUTO; /* auto */
+ }
+ else
+ daccess_np = concat(daccess_np, "|(", optarg, ")", NULL);
- case 'o': /* start offset */
- if (sscanf(argv[optind] + 2, "%d%n", &daccess.start_off, &pos)
- != 1)
- TELL("Bad format -- ");
- if (argv[optind][pos + 2] != '\0')
- TELL("Bad format -- ");
- break;
+ if (daccess.def_number < 0)
+ daccess.def_number = 0;
- case 'r': /* remove from word */
- if (strprefix("yes", argv[optind] + 2))
- daccess.remove = 'y';
- else if (strprefix("no", argv[optind] + 2))
- daccess.remove = 'n';
- else
- TELL("Bad format -- ");
- break;
+ break;
- case 'w': /* max width */
- if (sscanf(argv[optind] + 2, "%d%n", &daccess.width, &pos) != 1)
- TELL("Bad format -- ");
- if (argv[optind][pos + 2] != '\0')
- TELL("Bad format -- ");
- break;
+ case 'U':
+ if (daccess_up == NULL)
+ {
+ daccess_up = concat("(", optarg, ")", NULL);
+ daccess.type |= DA_TYPE_AUTO; /* auto */
+ }
+ else
+ daccess_up = concat(daccess_up, "|(", optarg, ")", NULL);
- case 's': /* skip */
- if (sscanf(argv[optind] + 2, "%d%n", &daccess.skip, &pos) != 1)
- TELL("Bad format -- ");
- if (argv[optind][pos + 2] != '\0')
- TELL("Bad format -- ");
- break;
- }
+ if (daccess.def_number < 0)
+ daccess.def_number = 1;
- optind++;
- }
+ break;
- /* The width is mandatory */
- /* """""""""""""""""""""" */
- if (daccess.width <= 0)
- TELL("The required 'width' suboption must me greater than 0 -- ");
- }
+ case 'F':
+ daccess.type |= DA_TYPE_POS;
- break;
+ break;
case '?':
fputc('\n', stderr);
@@ -6735,7 +6717,7 @@ main(int argc, char * argv[])
free(local_ini_file);
}
- word_buffer = xcalloc(1, limits.word_length);
+ word_buffer = xcalloc(1, daccess.flength + limits.word_length + 1);
/* If some attributes were not set, set their default values */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */
@@ -6935,11 +6917,18 @@ main(int argc, char * argv[])
col_index = cols_number = 0;
}
- if (daccess_pattern
- && regcomp(&daccess_pattern_re, daccess_pattern, REG_EXTENDED | REG_NOSUB)
- != 0)
+ if (daccess_np
+ && regcomp(&daccess_np_re, daccess_np, REG_EXTENDED | REG_NOSUB) != 0)
+ {
+ fprintf(stderr, "Bad regular expression %s\n", daccess_np);
+
+ exit(EXIT_FAILURE);
+ }
+
+ if (daccess_up
+ && regcomp(&daccess_up_re, daccess_up, REG_EXTENDED | REG_NOSUB) != 0)
{
- fprintf(stderr, "Bad regular expression %s\n", daccess_pattern);
+ fprintf(stderr, "Bad regular expression %s\n", daccess_up);
exit(EXIT_FAILURE);
}
@@ -7702,85 +7691,24 @@ main(int argc, char * argv[])
}
}
- /* Save the original word */
- /* """""""""""""""""""""" */
- word = &word_a[wi];
- unaltered_word = xstrdup(word->str);
+ word = &word_a[wi];
- /* Possibly modify the word according to -S/-I/-E arguments */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ /* Make sure that daccess.length >= daccess.size */
+ /* with DA_TYPE_POS. */
+ /* """"""""""""""""""""