variable in which to store the completions.
- compgen_builtin: if the -V option is supplied, store the possible
completions into VARNAME instead of printing them on stdout. From a
- patch from Grisha Levit <grishalevit@gmail.com>
+ patch from Grisha Levit <grishalevit@gmail.com>, idea originally
+ from konsolebox <konsolebox@gmail.com> back in 2/2022
doc/bash.1,lib/readline/doc/rluser.texi
- compgen: document new -V option
- _rl_move_cursor_relative: when checking to see whether data is within
the invisible line, make sure to stay within the invisible line
line break boundaries
+ From a report by minipython <599192367@qq.com>
lib/readline/search.c
- dispose_saved_search_line: new function, either unsave the saved
- noninc_dosearch,rl_history_search_internal: call dispose_saved_search_line
before calling make_history_line_current
+lib/readline/misc.c
+ - _rl_start_using_history: free the undo list associated with
+ _rl_saved_line_for_history, if one exists. Have to watch out for
+ this causing pointer aliasing problems, maybe add a call to
+ _hs_search_history_data()
+
+ 4/28
+ ----
+pathexp.c
+ - sh_globsort: a sort specifier of `nosort' disables sorting completely
+
+doc/bash.1,doc/bashref.texi
+ - GLOBSORT: document `nosort' sort specifier
+
+bashline.c
+ - attempt_shell_completion: attempt completion with the empty command
+ for a null command word on a line with only whitespace following any
+ optional assignment statements
+ - attempt_shell_completion: make sure that the start of the command
+ word is not after rl_point before calling the programmable completion
+ for the initial word.
+ From a report by Grisha Levit <grishalevit@gmail.com>
+
+lib/readline/histexpand.c
+ - history_expand: don't read past the end of the string if it ends with
+ an incomplete multibyte character
+ From a report by Grisha Levit <grishalevit@gmail.com>
end == index of where word to be completed ends
if (s == start) we are doing command word completion for sure
if (e1 == end) we are at the end of the command name and completing it */
- if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
+ if (start == 0 && end == 0 && e != 0 && e1 < rl_end && text[0] == '\0') /* beginning of non-empty line */
foundcs = 0;
else if (start == end && start == s1 && e != 0 && e1 > end) /* beginning of command name, leading whitespace */
foundcs = 0;
+ else if (start == 0 && start == end && start < s1 && e != 0 && e1 > end && text[0] == '\0' && have_progcomps) /* no command name, leading whitespace only */
+ prog_complete_matches = programmable_completions (EMPTYCMD, text, s, e, &foundcs);
else if (e == 0 && e == s && text[0] == '\0' && have_progcomps) /* beginning of empty line */
prog_complete_matches = programmable_completions (EMPTYCMD, text, s, e, &foundcs);
else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
/* If we have defined a compspec for the initial (command) word, call
it and process the results like any other programmable completion. */
if (in_command_position && have_progcomps && foundcs == 0 && iw_compspec)
- prog_complete_matches = programmable_completions (INITIALWORD, text, s, e, &foundcs);
+ {
+ /* Do some sanity checking on S and E. Room for more here. */
+ if (s > rl_point)
+ s = rl_point;
+ if (e > rl_end)
+ e = rl_end;
+ prog_complete_matches = programmable_completions (INITIALWORD, text, s, e, &foundcs);
+ }
FREE (n);
/* XXX - if we found a COMPSPEC for the command, just return whatever
.IR blocks ,
which sort the files on name, file size, modification time, access time,
inode change time, and number of blocks, respectively.
-For example, a value of \fB\-mtime\fP sorts the results in descending
+For example, a value of \fI\-mtime\fP sorts the results in descending
order by modification time (newest first).
+A sort specifier of \fInosort\fP disables sorting completely; the results
+are returned in the order they are read from the file system,.
If the sort specifier is missing, it defaults to \fIname\fP,
so a value of \fI+\fP is equivalent to the null string,
and a value of \fI-\fP sorts by name in descending order.
For example, a value of @code{-mtime} sorts the results in descending
order by modification time (newest first).
+A sort specifier of @samp{nosort} disables sorting completely; the results
+are returned in the order they are read from the file system,.
+
If the sort specifier is missing, it defaults to @var{name},
so a value of @samp{+} is equivalent to the null string,
and a value of @samp{-} sorts by name in descending order.
c = tchar;
memset (mb, 0, sizeof (mb));
- for (k = 0; k < MB_LEN_MAX; k++)
+ for (k = 0; k < MB_LEN_MAX && i < l; k++)
{
mb[k] = (char)c;
memset (&ps, 0, sizeof (mbstate_t));
_rl_start_using_history (void)
{
using_history ();
+#if 1
+ if (_rl_saved_line_for_history && _rl_saved_line_for_history->data)
+ _rl_free_undo_list ((UNDO_LIST *)_rl_saved_line_for_history->data);
+#endif
_rl_free_saved_history_line ();
_rl_history_search_pos = -99; /* some random invalid history position */
}
break;
}
+ /* If we didn't insert n and there are pending bytes, we need to insert
+ them if _rl_insert_char didn't do that on its own. */
+
if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
{
/* setting rl_pending_input inhibits setting rl_last_func so we do it
rl_executing_keyseq[rl_key_sequence_length = 0] = '\0';
r = rl_execute_next (n);
}
-
return r;
}
/* Functions to handle sorting glob results in different ways depending on
the value of the GLOBSORT variable. */
-static int glob_sorttype = STAT_NONE;
+static int glob_sorttype = SORT_NONE;
static STRING_INT_ALIST sorttypes[] = {
- { "name", STAT_NAME },
- { "size", STAT_SIZE },
- { "mtime", STAT_MTIME },
- { "atime", STAT_ATIME },
- { "ctime", STAT_CTIME },
- { "blocks", STAT_BLOCKS },
+ { "name", SORT_NAME },
+ { "size", SORT_SIZE },
+ { "mtime", SORT_MTIME },
+ { "atime", SORT_ATIME },
+ { "ctime", SORT_CTIME },
+ { "blocks", SORT_BLOCKS },
+ { "nosort", SORT_NOSORT },
{ (char *)NULL, -1 }
};
int type;
type = find_string_in_alist (t, sorttypes, 0);
- return (type == -1 ? STAT_NONE : type);
+ return (type == -1 ? SORT_NONE : type);
}
void
char *val;
int r, t;
- glob_sorttype = STAT_NONE;
+ glob_sorttype = SORT_NONE;
val = get_string_value (varname);
if (val == 0 || *val == 0)
return;
val++; /* allow leading `+' but ignore it */
else if (*val == '-')
{
- r = STAT_REVERSE; /* leading `-' reverses sort order */
+ r = SORT_REVERSE; /* leading `-' reverses sort order */
val++;
}
{
/* A bare `+' means the default sort by name in ascending order; a bare
`-' means to sort by name in descending order. */
- glob_sorttype = STAT_NAME | r;
+ glob_sorttype = SORT_NAME | r;
return;
}
t = glob_findtype (val);
/* any other value is equivalent to the historical behavior */
- glob_sorttype = (t == STAT_NONE) ? t : t | r;
+ glob_sorttype = (t == SORT_NONE) ? t : t | r;
}
static int
globsort_namecmp (char **s1, char **s2)
{
- return ((glob_sorttype < STAT_REVERSE) ? strvec_posixcmp (s1, s2) : strvec_posixcmp (s2, s1));
+ return ((glob_sorttype < SORT_REVERSE) ? strvec_posixcmp (s1, s2) : strvec_posixcmp (s2, s1));
}
static int
globsort_sizecmp (struct globsort_t *g1, struct globsort_t *g2)
{
- return ((glob_sorttype < STAT_REVERSE) ? g1->st.size - g2->st.size : g2->st.size - g1->st.size);
+ return ((glob_sorttype < SORT_REVERSE) ? g1->st.size - g2->st.size : g2->st.size - g1->st.size);
}
static int
int t;
struct timespec t1, t2;
- t = (glob_sorttype < STAT_REVERSE) ? glob_sorttype : glob_sorttype - STAT_REVERSE;
- if (t == STAT_MTIME)
+ t = (glob_sorttype < SORT_REVERSE) ? glob_sorttype : glob_sorttype - SORT_REVERSE;
+ if (t == SORT_MTIME)
{
t1 = g1->st.mtime;
t2 = g2->st.mtime;
}
- else if (t == STAT_ATIME)
+ else if (t == SORT_ATIME)
{
t1 = g1->st.atime;
t2 = g2->st.atime;
t2 = g2->st.ctime;
}
- return ((glob_sorttype < STAT_REVERSE) ? timespec_cmp (t1, t2) : timespec_cmp (t2, t1));
+ return ((glob_sorttype < SORT_REVERSE) ? timespec_cmp (t1, t2) : timespec_cmp (t2, t1));
}
static int
globsort_blockscmp (struct globsort_t *g1, struct globsort_t *g2)
{
- return ((glob_sorttype < STAT_REVERSE) ? g1->st.blocks - g2->st.blocks : g2->st.blocks - g1->st.blocks);
+ return ((glob_sorttype < SORT_REVERSE) ? g1->st.blocks - g2->st.blocks : g2->st.blocks - g1->st.blocks);
}
static struct globsort_t *
int t;
QSFUNC *sortfunc;
- t = (glob_sorttype < STAT_REVERSE) ? glob_sorttype : glob_sorttype - STAT_REVERSE;
+ t = (glob_sorttype < SORT_REVERSE) ? glob_sorttype : glob_sorttype - SORT_REVERSE;
switch (t)
{
- case STAT_SIZE:
+ case SORT_SIZE:
sortfunc = (QSFUNC *)globsort_sizecmp;
break;
- case STAT_ATIME:
- case STAT_MTIME:
- case STAT_CTIME:
+ case SORT_ATIME:
+ case SORT_MTIME:
+ case SORT_CTIME:
sortfunc = (QSFUNC *)globsort_timecmp;
break;
- case STAT_BLOCKS:
+ case SORT_BLOCKS:
sortfunc = (QSFUNC *)globsort_blockscmp;
break;
default:
size_t rlen;
struct globsort_t *garray;
- if (glob_sorttype == STAT_NONE || glob_sorttype == STAT_NAME)
+ if (glob_sorttype == SORT_NOSORT || glob_sorttype == (SORT_NOSORT|SORT_REVERSE))
+ return;
+
+ if (glob_sorttype == SORT_NONE || glob_sorttype == SORT_NAME)
globsort_sortbyname (results); /* posix sort */
- else if (glob_sorttype == (STAT_NAME|STAT_REVERSE))
+ else if (glob_sorttype == (SORT_NAME|SORT_REVERSE))
globsort_sortbyname (results); /* posix sort reverse order */
else
{
extern void ignore_glob_matches (char **);
/* Definitions for glob sorting */
-#define STAT_NONE 0
-#define STAT_NAME 1
-#define STAT_SIZE 2
-#define STAT_MTIME 3
-#define STAT_ATIME 4
-#define STAT_CTIME 5
-#define STAT_BLOCKS 6
-
-#define STAT_REVERSE 128
+#define SORT_NONE 0
+#define SORT_NAME 1
+#define SORT_SIZE 2
+#define SORT_MTIME 3
+#define SORT_ATIME 4
+#define SORT_CTIME 5
+#define SORT_BLOCKS 6
+#define SORT_NOSORT 7
+
+#define SORT_REVERSE 128
extern void setup_globsort (const char *);