diff options
author | pgen <p.gen.progs@gmail.com> | 2016-03-11 20:45:06 +0100 |
---|---|---|
committer | pgen <p.gen.progs@gmail.com> | 2016-03-11 22:39:25 +0100 |
commit | 2e88be0fdd2cf5ee867237bb11a4483fd04dc53c (patch) | |
tree | 0a1eb82cbf072c7d51fad2061727482e6bb67a68 | |
parent | 1c9c8154061c35a58939d01be92f182689d09ca9 (diff) |
Fix the -s option and add a search by regular expression syntax
- syntax change:
- use the -s/... syntax for regular expression search
- use the -s#... syntax for absolute positioning
- use the -s... syntax for prefix search
- clarify the documentation
- ensure that the words array is correctly updated after previous possible
alterations
-rw-r--r-- | smenu.1 | 29 | ||||
-rw-r--r-- | smenu.c | 163 |
2 files changed, 136 insertions, 56 deletions
@@ -243,22 +243,31 @@ Note that if this mode each column has the same width. .IP "\fB-s\fP \fIpattern\fP" Pre-Position the cursor to the first word matching the specified pattern. -\fIpattern\fP" can be: +\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. +A "\fB#\fP" immediately followed by 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 the latest selectable +position. .IP * 2 -The string \fBlast\fP meaning that we want the initial position to be -on the last word. +A single "\fB#\fP" or the string \fB#last\fP to also set the initial +cursor position at the latest selectable word position. .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). +to be set at the position of the first word matching the given regular +expression. +.IP * 2 +A \fBprefix\fP string indicating that we want the cursor to be set on the +first word matching the string given (\fBCa\fP will match \fBCancel\fP +by example). .PP -Every failure will do nothing, resulting with the cursor set on the -first word. +Warning, when searching for a prefix or a regular expression, smenu +only look for them only after an eventual modification, so per example, +the command: +\f(CBsmenu -I/c/x/ -s/c <<< "a b c d"\fP won't find c and put the cursor +on \fBa\fP but \f(CBsmenu -I/c/x/v -s/c <<< "a b c d"\fP will find it and +put the cursor on the \fBx\fP substituting the \fBc\fP on screen only .RE .IP "\fB-m\fP \fImessage\fP" Displays a message above the window. Beware, it will truncated if it @@ -5512,6 +5512,8 @@ main(int argc, char *argv[]) word_a[count].special_level = special_level; + /* Save the non modified word in .orig if it has been altered */ + /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (strcmp(word, dest) != 0) word_a[count].orig = word; else @@ -5531,6 +5533,33 @@ main(int argc, char *argv[]) else word_a[count].is_last = 0; + /* Store the new max number of bytes in a word */ + /* """"""""""""""""""""""""""""""""""""""""""" */ + if ((size = (int) word_len) > tab_real_max_size) + tab_real_max_size = (int) word_len; + + /* Store the new max word width */ + /* """""""""""""""""""""""""""" */ + size = (int) mbstowcs(0, dest, 0); + + if ((size = wcswidth((tmpw = mb_strtowcs(dest)), size)) > tab_max_size) + tab_max_size = size; + + free(tmpw); + + /* When the visual only flag is set, we keep the unaltered word so */ + /* that it can be restituted even if its visual and searchable */ + /* representation may have been altered by the previous code */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + if ((word_a[count].is_selectable & include_visual_only) + | ((!word_a[count].is_selectable) & exclude_visual_only)) + { + free(word_a[count].orig); + word_a[count].orig = unaltered_word; + } + else + free(unaltered_word); + /* If the word is selectable insert it in the TST tree */ /* with its associated index in the input stream. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ @@ -5562,33 +5591,6 @@ main(int argc, char *argv[]) free(w); } - /* Store the new max number of bytes in a word */ - /* """"""""""""""""""""""""""""""""""""""""""" */ - if ((size = (int) word_len) > tab_real_max_size) - tab_real_max_size = (int) word_len; - - /* Store the new max word width */ - /* """""""""""""""""""""""""""" */ - size = (int) mbstowcs(0, dest, 0); - - if ((size = wcswidth((tmpw = mb_strtowcs(dest)), size)) > tab_max_size) - tab_max_size = size; - - free(tmpw); - - /* When the visual only flag is set, we keep the unaltered word so */ - /* that it can be restituted even if its visual and searchable */ - /* representation may have been altered by the previous code */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - if ((word_a[count].is_selectable & include_visual_only) - | ((!word_a[count].is_selectable) & exclude_visual_only)) - { - free(word_a[count].orig); - word_a[count].orig = unaltered_word; - } - else - free(unaltered_word); - /* One more word... */ /* """""""""""""""" */ if (count == limits.words) @@ -5753,38 +5755,107 @@ main(int argc, char *argv[]) last_selectable--; if (pre_selection_index == NULL) + /* option -s was not used */ + /* """""""""""""""""""""" */ current = first_selectable; - else if (strcmp(pre_selection_index, "last") == 0) - current = last_selectable; else if (*pre_selection_index == '/') { - wchar_t *w; + /* A regular expression is expected */ + /* """""""""""""""""""""""""""""""" */ + regex_t re; + int index; - new_current = last_selectable; - if (NULL != tst_prefix_search(tst, - w = mb_strtowcs(pre_selection_index + 1), - tst_cb_cli)) - current = new_current; + if (regcomp(&re, pre_selection_index + 1, REG_EXTENDED | REG_NOSUB) != 0) + { + fprintf(stderr, "Invalid regular expression (%s)\n", pre_selection_index); + + exit(EXIT_FAILURE); + } else - current = first_selectable; - free(w); + { + int found = 0; + char *word; + + for (index = first_selectable; index <= last_selectable; index++) + { + if (word_a[index].orig != NULL) + word = word_a[index].orig; + else + word = word_a[index].str; + + if (regexec(&re, word, (size_t) 0, NULL, 0) == 0) + { + current = index; + found = 1; + break; + } + } + + if (!found) + current = first_selectable; + } } else if (*pre_selection_index != '\0') { - current = atoi(pre_selection_index); - if (current >= count) - current = count - 1; - if (!word_a[current].is_selectable) + /* A prefix string or an index is expected */ + /* """"""""""""""""""""""""""""""""""""""" */ + size_t len; + char *ptr = pre_selection_index; + + if (*ptr == '#') { - if (current > last_selectable) + /* An index is expected */ + /* """""""""""""""""""" */ + ptr++; + + if (sscanf(ptr, "%d%n", ¤t, &len) == 1 && len == strlen(ptr)) + { + /* We got an index (numeric value) */ + /* """"""""""""""""""""""""""""""" */ + if (current < 0) + current = first_selectable; + + if (current >= count) + current = count - 1; + + if (!word_a[current].is_selectable) + { + if (current > last_selectable) + current = last_selectable; + else if (current < first_selectable) + current = first_selectable; + else + while (current > first_selectable && !word_a[current].is_selectable) + current--; + } + } + else if (*ptr == '\0' || strcmp(ptr, "last") == 0) + /* We got a special index (empty or last) */ + /* """""""""""""""""""""""""""""""""""""" */ current = last_selectable; - else if (current < first_selectable) - current = first_selectable; else - while (current > first_selectable && !word_a[current].is_selectable) - current--; + { + fprintf(stderr, "Invalid index (%s)\n", ptr); + + exit(EXIT_FAILURE); + } + } + else + { + /* A prefix is expected */ + /* """""""""""""""""""" */ + wchar_t *w; + + new_current = last_selectable; + if (NULL != tst_prefix_search(tst, w = mb_strtowcs(ptr), tst_cb_cli)) + current = new_current; + else + current = first_selectable; + free(w); } } + else + current = first_selectable; /* We've finished reading from stdin */ /* we will now get the inputs from the controlling terminal if any */ |