1 From jwe@che.utexas.edu Wed Sep 21 17:23:40 1994
3 Return-Path: jwe@che.utexas.edu
4 Received: from po.CWRU.Edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.8.1+cwru/CWRU-2.1-ins)
5 id RAA04010; Wed, 21 Sep 1994 17:23:39 -0400 (from jwe@che.utexas.edu for <chet@odin.INS.CWRU.Edu>)
6 Received: from life.ai.mit.edu (life.ai.mit.edu [128.52.32.80]) by po.CWRU.Edu with SMTP (8.6.8.1+cwru/CWRU-2.2)
7 id RAA02121; Wed, 21 Sep 1994 17:23:28 -0400 (from jwe@che.utexas.edu for <chet@po.cwru.edu>)
8 Received: from schoch.che.utexas.edu by life.ai.mit.edu (4.1/AI-4.10) for chet@po.cwru.edu id AA09989; Wed, 21 Sep 94 17:23:17 EDT
9 Received: from localhost (jwe@localhost) by schoch.che.utexas.edu (8.6.8.1/8.6) with SMTP id QAA05737; Wed, 21 Sep 1994 16:22:01 -0500
10 Message-Id: <199409212122.QAA05737@schoch.che.utexas.edu>
12 Cc: bug-bash@prep.ai.mit.edu
13 Subject: Re: Completion feature possible?
14 In-Reply-To: Your message of 21 Sep 94 13:30:22 EDT
15 Date: Wed, 21 Sep 94 16:22:00 EDT
16 From: John Eaton <jwe@che.utexas.edu>
18 Gregory F. March <march@tudor.com> wrote:
20 : I was having a discussion about MH with one of my friends the other
21 : day and I got to thinking that the +folder/subfolder scheme for naming
22 : mail folders is a real pain because completion doesn't work on
23 : them. Someone then mentioned that zsh (I think) has the ability to
24 : specify how to complete (I guess where to look for the files) for
25 : different prefixes. Bash right now knows about '@', '~', and '$' (any
26 : others?). It would be really helpful if one could define something
29 : completion '+' "$HOME/Mail"
31 : in a config file someplace. Would this be easy? Is there a list of
32 : TODO item that someone might want to add this to?
34 It would be nice to have a general completion feature like this.
36 Until that happens, maybe you will find the following patch useful.
37 It makes MH folder name completion work with bash. The diffs are
38 relative to version 1.14.2.
40 I realize that changes to readline.c and and complete.c are not good
41 since they add some MH-specific stuff to the readline code and not to
42 bash, but when I first wrote this, I had no idea what else to do.
44 Chet, would you consider adding this if it were cleaned up a bit?
45 Made optional with cpp conditionals?
47 This feature has been very useful to me for the last several years
48 (since about 1.05 or 1.06, I think).
53 John W. Eaton | 4.3BSD is not perfect. -- Leffler, et al. (1989).
57 -------------------------------cut here-------------------------------
58 diff -rc bash-1.14.2/bashline.c bash-1.14.2.local/bashline.c
59 *** bash-1.14.2/bashline.c Wed Aug 3 09:32:45 1994
60 --- bash-1.14.2.local/bashline.c Wed Sep 21 15:39:04 1994
64 static char *hostname_completion_function ();
65 static char *command_word_completion_function ();
66 static char *command_subst_completion_function ();
67 + static char *mh_folder_completion_function ();
69 static void snarf_hosts_from_file (), add_host_name ();
70 static void sort_hostname_list ();
74 bash_complete_username_internal (),
75 bash_complete_hostname (), bash_possible_hostname_completions (),
76 bash_complete_hostname_internal (),
77 + bash_complete_mh_folder (), bash_possible_mh_folder_completions (),
78 + bash_complete_mh_folder_internal (),
79 bash_complete_variable (), bash_possible_variable_completions (),
80 bash_complete_variable_internal (),
81 bash_complete_command (), bash_possible_command_completions (),
84 rl_terminal_name = get_string_value ("TERM");
86 rl_outstream = stderr;
87 ! rl_special_prefixes = "$@";
89 /* Allow conditional parsing of the ~/.inputrc file. */
90 rl_readline_name = "Bash";
92 rl_terminal_name = get_string_value ("TERM");
94 rl_outstream = stderr;
95 ! rl_special_prefixes = "$@+";
97 /* Allow conditional parsing of the ~/.inputrc file. */
98 rl_readline_name = "Bash";
102 rl_bind_key_in_map ('@', bash_possible_hostname_completions,
105 + rl_add_defun ("complete-mh-folder", bash_complete_mh_folder, META('+'));
106 + rl_add_defun ("possible-mh-folder-completions",
107 + bash_possible_mh_folder_completions, -1);
108 + rl_bind_key_in_map ('+', bash_possible_mh_folder_completions,
109 + emacs_ctlx_keymap);
111 rl_add_defun ("complete-variable", bash_complete_variable, -1);
112 rl_bind_key_in_map ('$', bash_complete_variable, emacs_meta_keymap);
113 rl_add_defun ("possible-variable-completions",
117 if (!matches && *text == '@')
118 matches = completion_matches (text, hostname_completion_function);
120 + /* Another one. Why not? If the word starts in '+', then look for
121 + matching mh folders for completion first. */
122 + if (!matches && *text == '+')
124 + matches = completion_matches (text, mh_folder_completion_function);
127 /* And last, (but not least) if this word is in a command position, then
128 complete over possible command names, including aliases, functions,
129 and command names. */
133 return ((char *)NULL);
136 + /* How about a completion function for mh folders? */
138 + mh_folder_completion_function (text, state)
142 + extern int rl_filename_completion_desired;
144 + extern char *get_mh_path ();
146 + static char *mh_path = (char *)NULL;
152 + static char *mh_folder_hint = (char *)NULL;
154 + /* If we don't have any state, make some. */
157 + val = (char *)NULL;
162 + mh_path = get_mh_path ();
163 + if (!mh_path && !(hint[1] == '/' || hint[1] == '.'))
164 + return ((char *)NULL);
166 + len = strlen (mh_path);
169 + if (mh_folder_hint)
170 + free (mh_folder_hint);
176 + mh_folder_hint = (char *)xmalloc (2 + len + strlen (hint));
177 + if (*hint == '/' || *hint == '.') {
179 + sprintf (mh_folder_hint, "%s", hint);
181 + sprintf (mh_folder_hint, "%s/%s", mh_path, hint);
183 + istate = (val != (char *)NULL);
186 + val = filename_completion_function (mh_folder_hint, istate);
191 + return ((char *)NULL);
195 + char *ptr = val + len + 1, *temp;
197 + int status = stat (val, &sb);
200 + return ((char *)NULL);
202 + if ((sb.st_mode & S_IFDIR) == S_IFDIR)
204 + temp = (char *)xmalloc (2 + strlen (ptr));
206 + strcpy (temp + 1, ptr);
211 + rl_filename_completion_desired = 1;
223 /* History and alias expand the line. */
225 history_expand_line_internal (line)
230 bash_specific_completion
231 (what_to_do, (Function *)username_completion_function);
235 + bash_complete_mh_folder (ignore, ignore2)
236 + int ignore, ignore2;
238 + bash_complete_mh_folder_internal (TAB);
242 + bash_possible_mh_folder_completions (ignore, ignore2)
243 + int ignore, ignore2;
245 + bash_complete_mh_folder_internal ('?');
249 + bash_complete_mh_folder_internal (what_to_do)
252 + Function *orig_func;
253 + CPPFunction *orig_attempt_func;
254 + char *orig_rl_completer_word_break_characters;
255 + extern char *rl_completer_word_break_characters;
257 + orig_func = rl_completion_entry_function;
258 + orig_attempt_func = rl_attempted_completion_function;
259 + orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
260 + rl_completion_entry_function = (Function *)mh_folder_completion_function;
261 + rl_attempted_completion_function = (CPPFunction *)NULL;
262 + rl_completer_word_break_characters = " \t\n\"\'";
264 + rl_complete_internal (what_to_do);
266 + rl_completion_entry_function = orig_func;
267 + rl_attempted_completion_function = orig_attempt_func;
268 + rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
272 Only in bash-1.14.2.local: bashline.c.orig
273 diff -rc bash-1.14.2/lib/readline/complete.c bash-1.14.2.local/lib/readline/complete.c
274 *** bash-1.14.2/lib/readline/complete.c Tue Jul 26 12:59:57 1994
275 --- bash-1.14.2.local/lib/readline/complete.c Wed Sep 21 15:41:19 1994
278 if (rl_filename_completion_desired)
281 ! char *filename = tilde_expand (matches[0]);
283 ! if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode))
285 ! if (rl_line_buffer[rl_point] != '/')
286 ! rl_insert_text ("/");
290 ! if (rl_point == rl_end)
291 ! rl_insert_text (temp_string);
298 if (rl_filename_completion_desired)
301 ! char *tilde_expand ();
302 ! char *plus_expand ();
303 ! char *filename = (char *) NULL;
305 ! switch (*matches[0])
308 ! filename = plus_expand (matches[0]);
312 ! filename = tilde_expand (matches[0]);
318 ! if ((stat (filename, &finfo) == 0)
319 ! && S_ISDIR (finfo.st_mode))
321 ! if (rl_line_buffer[rl_point] != '/')
322 ! rl_insert_text ("/");
326 ! if (rl_point == rl_end)
327 ! rl_insert_text (temp_string);
334 Only in bash-1.14.2.local/lib/readline: diffs
335 diff -rc bash-1.14.2/lib/readline/readline.c bash-1.14.2.local/lib/readline/readline.c
336 *** bash-1.14.2/lib/readline/readline.c Fri Aug 12 12:47:46 1994
337 --- bash-1.14.2.local/lib/readline/readline.c Wed Sep 21 15:36:07 1994
341 #define READLINE_LIBRARY
344 + #include <string.h>
345 #include <sys/types.h>
347 #if !defined (NO_SYS_FILE)
355 + #define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
360 + static FILE *fp = (FILE *)NULL;
361 + char buf[512]; /* XXX */
362 + char profile[512]; /* XXX */
367 + temp_home = (char *)getenv ("HOME");
369 + return ((char *)NULL);
371 + strcpy (profile, temp_home);
372 + strcat (profile, "/.mh_profile");
377 + fp = fopen (profile, "r");
378 + if (fp == (FILE *)NULL)
379 + return ((char *)NULL);
381 + while (fgets (buf, 512, fp) != (char *)NULL) /* XXX */
383 + if ((bp = strstr (buf, "Path:")) != (char *)NULL)
386 + while (whitespace (*bp))
390 + return ((char *)NULL);
392 + temp_path = (char *)xmalloc (3 + strlen (bp) + strlen (temp_home));
394 + strcpy (temp_path, temp_home);
395 + strcat (temp_path, "/");
396 + strcat (temp_path, bp);
400 + while (!(cr_whitespace (*bp)))
409 + return ((char *)NULL);
412 + /* Expand FILENAME if it begins with a plus. This always returns
415 + plus_expand (filename)
418 + static char *dirname = (char *)NULL;
420 + if (filename && *filename == '+')
422 + char *mh_path = get_mh_path ();
424 + if (filename[1] == '/' || filename[1] == '.')
426 + dirname = (char *)xmalloc (1 + strlen (filename));
428 + strcpy(dirname, filename+1);
435 + dirname = (char *)xmalloc (1 + strlen (filename) + strlen (mh_path));
437 + strcpy (dirname, mh_path);
438 + strcat (dirname, "/");
439 + strcat (dirname, filename+1);
444 + return (char *)NULL;