aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r--src/nvim/buffer.c97
1 files changed, 90 insertions, 7 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 24ba43676a..7c8f93163a 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1618,6 +1618,7 @@ void enter_buffer(buf_T *buf)
if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
(void)did_set_spelllang(curwin);
}
+ curbuf->b_last_used = time(NULL);
redraw_later(NOT_VALID);
}
@@ -2250,6 +2251,23 @@ int buflist_findpat(
return match;
}
+typedef struct {
+ buf_T *buf;
+ char_u *match;
+} bufmatch_T;
+
+/// Compare functions for qsort() below, that compares b_last_used.
+static int
+buf_time_compare(const void *s1, const void *s2)
+{
+ buf_T *buf1 = *(buf_T **)s1;
+ buf_T *buf2 = *(buf_T **)s2;
+
+ if (buf1->b_last_used == buf2->b_last_used) {
+ return 0;
+ }
+ return buf1->b_last_used > buf2->b_last_used ? -1 : 1;
+}
/*
* Find all buffer names that match.
@@ -2263,6 +2281,7 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options)
char_u *p;
int attempt;
char_u *patc;
+ bufmatch_T *matches = NULL;
*num_file = 0; // return values in case of FAIL
*file = NULL;
@@ -2313,7 +2332,13 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options)
} else {
p = vim_strsave(p);
}
- (*file)[count++] = p;
+ if (matches != NULL) {
+ matches[count].buf = buf;
+ matches[count].match = p;
+ count++;
+ } else {
+ (*file)[count++] = p;
+ }
}
}
}
@@ -2322,6 +2347,10 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options)
}
if (round == 1) {
*file = xmalloc((size_t)count * sizeof(**file));
+
+ if (options & WILD_BUFLASTUSED) {
+ matches = xmalloc((size_t)count * sizeof(*matches));
+ }
}
}
vim_regfree(regmatch.regprog);
@@ -2334,6 +2363,25 @@ int ExpandBufnames(char_u *pat, int *num_file, char_u ***file, int options)
xfree(patc);
}
+ if (matches != NULL) {
+ if (count > 1) {
+ qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare);
+ }
+
+ // if the current buffer is first in the list, place it at the end
+ if (matches[0].buf == curbuf) {
+ for (int i = 1; i < count; i++) {
+ (*file)[i-1] = matches[i].match;
+ }
+ (*file)[count-1] = matches[0].match;
+ } else {
+ for (int i = 0; i < count; i++) {
+ (*file)[i] = matches[i].match;
+ }
+ }
+ xfree(matches);
+ }
+
*num_file = count;
return count == 0 ? FAIL : OK;
}
@@ -2594,11 +2642,35 @@ linenr_T buflist_findlnum(buf_T *buf)
// List all known file names (for :files and :buffers command).
void buflist_list(exarg_T *eap)
{
- buf_T *buf;
+ buf_T *buf = firstbuf;
int len;
int i;
- for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next) {
+ garray_T buflist;
+ buf_T **buflist_data = NULL, **p;
+
+ if (vim_strchr(eap->arg, 't')) {
+ ga_init(&buflist, sizeof(buf_T *), 50);
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next) {
+ ga_grow(&buflist, 1);
+ ((buf_T **)buflist.ga_data)[buflist.ga_len++] = buf;
+ }
+
+ qsort(buflist.ga_data, (size_t)buflist.ga_len,
+ sizeof(buf_T *), buf_time_compare);
+
+ p = buflist_data = (buf_T **)buflist.ga_data;
+ buf = *p;
+ }
+
+ for (;
+ buf != NULL && !got_int;
+ buf = buflist_data
+ ? (++p < buflist_data + buflist.ga_len ? *p : NULL)
+ : buf->b_next) {
+ const bool is_terminal = buf->terminal;
+ const bool job_running = buf->terminal && terminal_running(buf->terminal);
+
// skip unspecified buffers
if ((!buf->b_p_bl && !eap->forceit && !strchr((char *)eap->arg, 'u'))
|| (strchr((char *)eap->arg, 'u') && buf->b_p_bl)
@@ -2608,6 +2680,8 @@ void buflist_list(exarg_T *eap)
&& (buf->b_ml.ml_mfp == NULL || buf->b_nwindows == 0))
|| (strchr((char *)eap->arg, 'h')
&& (buf->b_ml.ml_mfp == NULL || buf->b_nwindows != 0))
+ || (strchr((char *)eap->arg, 'R') && (!is_terminal || !job_running))
+ || (strchr((char *)eap->arg, 'F') && (!is_terminal || job_running))
|| (strchr((char *)eap->arg, '-') && buf->b_p_ma)
|| (strchr((char *)eap->arg, '=') && !buf->b_p_ro)
|| (strchr((char *)eap->arg, 'x') && !(buf->b_flags & BF_READERR))
@@ -2654,13 +2728,22 @@ void buflist_list(exarg_T *eap)
do {
IObuff[len++] = ' ';
} while (--i > 0 && len < IOSIZE - 18);
- vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len),
- _("line %" PRId64),
- buf == curbuf ? (int64_t)curwin->w_cursor.lnum
- : (int64_t)buflist_findlnum(buf));
+ if (vim_strchr(eap->arg, 't') && buf->b_last_used) {
+ add_time(IObuff + len, (size_t)(IOSIZE - len), buf->b_last_used);
+ } else {
+ vim_snprintf((char *)IObuff + len, (size_t)(IOSIZE - len),
+ _("line %" PRId64),
+ buf == curbuf ? (int64_t)curwin->w_cursor.lnum
+ : (int64_t)buflist_findlnum(buf));
+ }
+
msg_outtrans(IObuff);
line_breakcheck();
}
+
+ if (buflist_data) {
+ ga_clear(&buflist);
+ }
}
/*