* Simon Pamies wrote, On 27.12.2006 12:19 Uhr:
> * Simon Pamies wrote, On 27.12.2006 11:50 Uhr:
>> Hi All,
>>
>> I had some problems using the :buffer listing. If you have many files
>> (read 30+) open, the :buffer list is cluttered up with long directory
>> names (especially if working with files scattered over many directories)
>> and you loose overview. Switching to another buffer can be a real pain
>> especially because the completion completes on directory names. If you
>> have directories named like files then you're typing stuff w/o getting
>> to your file.
>
> I just discovered a bug introduced shortly before creating the diffs: If
> hitting WCHAR after menu is shown, completion will still take
> directories. Will fix that in the next few days.
Regardless if I'll find a possibility to implement this using plugins
here the fixed code (buffer.c.diff, others remain unchanged). Works for me.
Simon Pamies
Index: buffer.c
===================================================================
--- buffer.c (revision 195)
+++ buffer.c (working copy)
@@ -47,6 +47,7 @@
static void free_buffer __ARGS((buf_T *));
static void free_buffer_stuff __ARGS((buf_T *buf, int free_options));
static void clear_wininfo __ARGS((buf_T *buf));
+int fill_shortnames __ARGS(());
#ifdef UNIX
# define dev_T dev_t
@@ -221,6 +222,11 @@
foldUpdateAll(curwin);
#endif
+ /* spamsch: Trigger setting of shortname but only
+ * option emacsbuflist is set */
+ if (p_embl)
+ fill_shortnames();
+
#ifdef FEAT_AUTOCMD
/* need to set w_topline, unless some autocommand already did that. */
if (!(curwin->w_valid & VALID_TOPLINE))
@@ -449,6 +455,7 @@
#endif
vim_free(buf->b_ffname);
vim_free(buf->b_sfname);
+ vim_free(buf->b_sname);
if (buf->b_prev == NULL)
firstbuf = buf->b_next;
else
@@ -1569,6 +1576,8 @@
buf->b_ffname = NULL;
vim_free(buf->b_sfname);
buf->b_sfname = NULL;
+ vim_free(buf->b_sname);
+ buf->b_sname = NULL;
if (buf != curbuf)
free_buffer(buf);
return NULL;
@@ -1992,6 +2001,7 @@
int diffmode; /* find diff-mode buffers only */
{
buf_T *buf;
+ buf_T *sbuf;
regprog_T *prog;
int match = -1;
int find_listed;
@@ -2059,7 +2069,22 @@
{
if (match >= 0) /* already found a match */
{
- match = -2;
+
+ /* spamsch: This case can happen if the
+ * short buffer name is used and we have
+ * two buffers with the same name. But because
+ * only one buffer shortname can match exactly
+ * the given one we check the buffer names
+ * for an exact match. */
+ match = -2;
+
+ if (p_embl) /* Check only if option is set */
+ for (sbuf = firstbuf; sbuf != NULL; sbuf =
sbuf->b_next)
+ if (STRCMP(sbuf->b_sname, pattern) == 0) {
+ match = sbuf->b_fnum;
+ break;
+ }
+
break;
}
match = buf->b_fnum; /* remember first match */
@@ -2088,12 +2113,71 @@
}
#endif
+/*
+ * spamsch: Go through the buffer list and fill
+ * the field b_sname for each buffer
+ */
+ int
+fill_shortnames()
+{
+ buf_T *buf;
+ buf_T *sbuf;
+ char_u *pos;
+ int counter;
+ int fcounter;
+
+ counter = fcounter = 0;
+ for (buf = firstbuf; buf != NULL; buf = buf->b_next) {
+
+ buf->b_sname = NULL;
+
+ if (buf->b_ffname != NULL && buf->b_p_bl) {
+ counter++;
+
+ /* We want to have the filename so we search for
+ * the last slash and get stuff behind it */
+ pos = vim_strrchr(buf->b_ffname, '/');
+
+ char_u *cpstr;
+ cpstr = (char_u *)alloc(255 * sizeof(char_u));
+ if (cpstr == NULL)
+ return FAIL;
+
+ if (pos != NULL) {
+ vim_strncpy(cpstr, pos+1, (unsigned)STRLEN(pos)-1);
+
+ for (sbuf = firstbuf; sbuf != NULL; sbuf = sbuf->b_next)
+ if (buf != sbuf)
+ if (sbuf->b_sname != NULL)
+ if (STRCMP(sbuf->b_sname, cpstr) == 0) {
+ char bnamenum[255];
+ sprintf(bnamenum, "<%d>", ++fcounter);
+ STRCAT(cpstr, bnamenum);
+ break;
+ }
+
+ } else {
+ STRCPY(cpstr, buf->b_ffname);
+ }
+
+ /* Put name into buf->b_sname */
+ buf->b_sname = vim_strsave(cpstr);
+ vim_free(cpstr);
+ }
+ }
+
+ return OK;
+
+}
+
+
#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
/*
* Find all buffer names that match.
* For command line expansion of ":buf" and ":sbuf".
* Return OK if matches found, FAIL otherwise.
+ *
*/
int
ExpandBufnames(pat, num_file, file, options)
@@ -2206,11 +2290,24 @@
{
char_u *match;
- /* First try the short file name, then the long file name. */
- match = fname_match(prog, buf->b_sfname);
- if (match == NULL)
- match = fname_match(prog, buf->b_ffname);
+ /* spamsch: First try b_sname as it contains the shortname */
+ if (p_embl) {
+ match = fname_match(prog, buf->b_sname);
+ /* I emacsbuflist is set then we only try to complete
+ on b_sname */
+ return match;
+
+ } else
+ match = fname_match(prog, buf->b_sfname);
+
+ if (match == NULL) {
+ /* Try the short file name, then the long file name. */
+ match = fname_match(prog, buf->b_sfname);
+ if (match == NULL)
+ match = fname_match(prog, buf->b_ffname);
+ }
+
return match;
}
@@ -2549,8 +2646,10 @@
/* Removing the name. */
vim_free(buf->b_ffname);
vim_free(buf->b_sfname);
+ vim_free(buf->b_sname);
buf->b_ffname = NULL;
buf->b_sfname = NULL;
+ buf->b_sname = NULL;
#ifdef UNIX
st.st_dev = (dev_T)-1;
#endif
@@ -2602,8 +2701,10 @@
#endif
vim_free(buf->b_ffname);
vim_free(buf->b_sfname);
+ vim_free(buf->b_sname);
buf->b_ffname = ffname;
buf->b_sfname = sfname;
+ buf->b_sname = NULL;
}
buf->b_fname = buf->b_sfname;
#ifdef UNIX
@@ -2640,8 +2741,10 @@
{
vim_free(buf->b_sfname);
vim_free(buf->b_ffname);
+ vim_free(buf->b_sname);
buf->b_ffname = vim_strsave(name);
buf->b_sfname = NULL;
+ buf->b_sname = NULL;
/* Allocate ffname and expand into full path. Also resolves .lnk
* files on Win32. */
fname_expand(buf, &buf->b_ffname, &buf->b_sfname);