aboutsummaryrefslogtreecommitdiffstats
path: root/CWRU/mh-folder-comp
diff options
context:
space:
mode:
Diffstat (limited to 'CWRU/mh-folder-comp')
-rw-r--r--CWRU/mh-folder-comp449
1 files changed, 449 insertions, 0 deletions
diff --git a/CWRU/mh-folder-comp b/CWRU/mh-folder-comp
new file mode 100644
index 0000000..905000c
--- /dev/null
+++ b/CWRU/mh-folder-comp
@@ -0,0 +1,449 @@
+From jwe@che.utexas.edu Wed Sep 21 17:23:40 1994
+Flags: 10
+Return-Path: jwe@che.utexas.edu
+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)
+ id RAA04010; Wed, 21 Sep 1994 17:23:39 -0400 (from jwe@che.utexas.edu for <chet@odin.INS.CWRU.Edu>)
+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)
+ id RAA02121; Wed, 21 Sep 1994 17:23:28 -0400 (from jwe@che.utexas.edu for <chet@po.cwru.edu>)
+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
+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
+Message-Id: <199409212122.QAA05737@schoch.che.utexas.edu>
+To: march@tudor.com
+Cc: bug-bash@prep.ai.mit.edu
+Subject: Re: Completion feature possible?
+In-Reply-To: Your message of 21 Sep 94 13:30:22 EDT
+Date: Wed, 21 Sep 94 16:22:00 EDT
+From: John Eaton <jwe@che.utexas.edu>
+
+Gregory F. March <march@tudor.com> wrote:
+
+: I was having a discussion about MH with one of my friends the other
+: day and I got to thinking that the +folder/subfolder scheme for naming
+: mail folders is a real pain because completion doesn't work on
+: them. Someone then mentioned that zsh (I think) has the ability to
+: specify how to complete (I guess where to look for the files) for
+: different prefixes. Bash right now knows about '@', '~', and '$' (any
+: others?). It would be really helpful if one could define something
+: like:
+:
+: completion '+' "$HOME/Mail"
+:
+: in a config file someplace. Would this be easy? Is there a list of
+: TODO item that someone might want to add this to?
+
+It would be nice to have a general completion feature like this.
+
+Until that happens, maybe you will find the following patch useful.
+It makes MH folder name completion work with bash. The diffs are
+relative to version 1.14.2.
+
+I realize that changes to readline.c and and complete.c are not good
+since they add some MH-specific stuff to the readline code and not to
+bash, but when I first wrote this, I had no idea what else to do.
+
+Chet, would you consider adding this if it were cleaned up a bit?
+Made optional with cpp conditionals?
+
+This feature has been very useful to me for the last several years
+(since about 1.05 or 1.06, I think).
+
+Thanks,
+
+--
+John W. Eaton | 4.3BSD is not perfect. -- Leffler, et al. (1989).
+jwe@che.utexas.edu |
+
+
+-------------------------------cut here-------------------------------
+diff -rc bash-1.14.2/bashline.c bash-1.14.2.local/bashline.c
+*** bash-1.14.2/bashline.c Wed Aug 3 09:32:45 1994
+--- bash-1.14.2.local/bashline.c Wed Sep 21 15:39:04 1994
+***************
+*** 58,63 ****
+--- 58,64 ----
+ static char *hostname_completion_function ();
+ static char *command_word_completion_function ();
+ static char *command_subst_completion_function ();
++ static char *mh_folder_completion_function ();
+
+ static void snarf_hosts_from_file (), add_host_name ();
+ static void sort_hostname_list ();
+***************
+*** 90,95 ****
+--- 91,98 ----
+ bash_complete_username_internal (),
+ bash_complete_hostname (), bash_possible_hostname_completions (),
+ bash_complete_hostname_internal (),
++ bash_complete_mh_folder (), bash_possible_mh_folder_completions (),
++ bash_complete_mh_folder_internal (),
+ bash_complete_variable (), bash_possible_variable_completions (),
+ bash_complete_variable_internal (),
+ bash_complete_command (), bash_possible_command_completions (),
+***************
+*** 134,140 ****
+ rl_terminal_name = get_string_value ("TERM");
+ rl_instream = stdin;
+ rl_outstream = stderr;
+! rl_special_prefixes = "$@";
+
+ /* Allow conditional parsing of the ~/.inputrc file. */
+ rl_readline_name = "Bash";
+--- 137,143 ----
+ rl_terminal_name = get_string_value ("TERM");
+ rl_instream = stdin;
+ rl_outstream = stderr;
+! rl_special_prefixes = "$@+";
+
+ /* Allow conditional parsing of the ~/.inputrc file. */
+ rl_readline_name = "Bash";
+***************
+*** 193,198 ****
+--- 196,207 ----
+ rl_bind_key_in_map ('@', bash_possible_hostname_completions,
+ emacs_ctlx_keymap);
+
++ rl_add_defun ("complete-mh-folder", bash_complete_mh_folder, META('+'));
++ rl_add_defun ("possible-mh-folder-completions",
++ bash_possible_mh_folder_completions, -1);
++ rl_bind_key_in_map ('+', bash_possible_mh_folder_completions,
++ emacs_ctlx_keymap);
++
+ rl_add_defun ("complete-variable", bash_complete_variable, -1);
+ rl_bind_key_in_map ('$', bash_complete_variable, emacs_meta_keymap);
+ rl_add_defun ("possible-variable-completions",
+***************
+*** 656,661 ****
+--- 665,677 ----
+ if (!matches && *text == '@')
+ matches = completion_matches (text, hostname_completion_function);
+
++ /* Another one. Why not? If the word starts in '+', then look for
++ matching mh folders for completion first. */
++ if (!matches && *text == '+')
++ {
++ matches = completion_matches (text, mh_folder_completion_function);
++ }
++
+ /* And last, (but not least) if this word is in a command position, then
+ complete over possible command names, including aliases, functions,
+ and command names. */
+***************
+*** 1077,1082 ****
+--- 1093,1185 ----
+ return ((char *)NULL);
+ }
+
++ /* How about a completion function for mh folders? */
++ static char *
++ mh_folder_completion_function (text, state)
++ int state;
++ char *text;
++ {
++ extern int rl_filename_completion_desired;
++
++ extern char *get_mh_path ();
++
++ static char *mh_path = (char *)NULL;
++ static int len;
++ static int istate;
++ static char *val;
++ char *hint;
++
++ static char *mh_folder_hint = (char *)NULL;
++
++ /* If we don't have any state, make some. */
++ if (!state)
++ {
++ val = (char *)NULL;
++
++ if (mh_path)
++ free (mh_path);
++
++ mh_path = get_mh_path ();
++ if (!mh_path && !(hint[1] == '/' || hint[1] == '.'))
++ return ((char *)NULL);
++
++ len = strlen (mh_path);
++ }
++
++ if (mh_folder_hint)
++ free (mh_folder_hint);
++
++ hint = text;
++ if (*hint == '+')
++ hint++;
++
++ mh_folder_hint = (char *)xmalloc (2 + len + strlen (hint));
++ if (*hint == '/' || *hint == '.') {
++ len = -1;
++ sprintf (mh_folder_hint, "%s", hint);
++ } else
++ sprintf (mh_folder_hint, "%s/%s", mh_path, hint);
++
++ istate = (val != (char *)NULL);
++
++ again:
++ val = filename_completion_function (mh_folder_hint, istate);
++ istate = 1;
++
++ if (!val)
++ {
++ return ((char *)NULL);
++ }
++ else
++ {
++ char *ptr = val + len + 1, *temp;
++ struct stat sb;
++ int status = stat (val, &sb);
++
++ if (status != 0)
++ return ((char *)NULL);
++
++ if ((sb.st_mode & S_IFDIR) == S_IFDIR)
++ {
++ temp = (char *)xmalloc (2 + strlen (ptr));
++ *temp = '+';
++ strcpy (temp + 1, ptr);
++
++ free (val);
++ val = "";
++
++ rl_filename_completion_desired = 1;
++
++ return (temp);
++ }
++ else
++ {
++ free (val);
++ }
++ goto again;
++ }
++ }
++
+ /* History and alias expand the line. */
+ static char *
+ history_expand_line_internal (line)
+***************
+*** 1628,1633 ****
+--- 1731,1773 ----
+ {
+ bash_specific_completion
+ (what_to_do, (Function *)username_completion_function);
++ }
++
++ static void
++ bash_complete_mh_folder (ignore, ignore2)
++ int ignore, ignore2;
++ {
++ bash_complete_mh_folder_internal (TAB);
++ }
++
++ static void
++ bash_possible_mh_folder_completions (ignore, ignore2)
++ int ignore, ignore2;
++ {
++ bash_complete_mh_folder_internal ('?');
++ }
++
++ static void
++ bash_complete_mh_folder_internal (what_to_do)
++ int what_to_do;
++ {
++ Function *orig_func;
++ CPPFunction *orig_attempt_func;
++ char *orig_rl_completer_word_break_characters;
++ extern char *rl_completer_word_break_characters;
++
++ orig_func = rl_completion_entry_function;
++ orig_attempt_func = rl_attempted_completion_function;
++ orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
++ rl_completion_entry_function = (Function *)mh_folder_completion_function;
++ rl_attempted_completion_function = (CPPFunction *)NULL;
++ rl_completer_word_break_characters = " \t\n\"\'";
++
++ rl_complete_internal (what_to_do);
++
++ rl_completion_entry_function = orig_func;
++ rl_attempted_completion_function = orig_attempt_func;
++ rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
+ }
+
+ static void
+Only in bash-1.14.2.local: bashline.c.orig
+diff -rc bash-1.14.2/lib/readline/complete.c bash-1.14.2.local/lib/readline/complete.c
+*** bash-1.14.2/lib/readline/complete.c Tue Jul 26 12:59:57 1994
+--- bash-1.14.2.local/lib/readline/complete.c Wed Sep 21 15:41:19 1994
+***************
+*** 733,751 ****
+ if (rl_filename_completion_desired)
+ {
+ struct stat finfo;
+! char *filename = tilde_expand (matches[0]);
+
+! if ((stat (filename, &finfo) == 0) && S_ISDIR (finfo.st_mode))
+ {
+! if (rl_line_buffer[rl_point] != '/')
+! rl_insert_text ("/");
+ }
+! else
+ {
+! if (rl_point == rl_end)
+! rl_insert_text (temp_string);
+ }
+- free (filename);
+ }
+ else
+ {
+--- 733,768 ----
+ if (rl_filename_completion_desired)
+ {
+ struct stat finfo;
+! char *tilde_expand ();
+! char *plus_expand ();
+! char *filename = (char *) NULL;
+
+! switch (*matches[0])
+ {
+! case '+':
+! filename = plus_expand (matches[0]);
+! break;
+! case '~':
+! default:
+! filename = tilde_expand (matches[0]);
+! break;
+ }
+!
+! if (filename)
+ {
+! if ((stat (filename, &finfo) == 0)
+! && S_ISDIR (finfo.st_mode))
+! {
+! if (rl_line_buffer[rl_point] != '/')
+! rl_insert_text ("/");
+! }
+! else
+! {
+! if (rl_point == rl_end)
+! rl_insert_text (temp_string);
+! }
+! free (filename);
+ }
+ }
+ else
+ {
+Only in bash-1.14.2.local/lib/readline: diffs
+diff -rc bash-1.14.2/lib/readline/readline.c bash-1.14.2.local/lib/readline/readline.c
+*** bash-1.14.2/lib/readline/readline.c Fri Aug 12 12:47:46 1994
+--- bash-1.14.2.local/lib/readline/readline.c Wed Sep 21 15:36:07 1994
+***************
+*** 23,28 ****
+--- 23,29 ----
+ #define READLINE_LIBRARY
+
+ #include <stdio.h>
++ #include <string.h>
+ #include <sys/types.h>
+ #include <fcntl.h>
+ #if !defined (NO_SYS_FILE)
+***************
+*** 3518,3523 ****
+--- 3519,3616 ----
+ }
+
+ #endif /* TEST */
++
++ #define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
++
++ char *
++ get_mh_path ()
++ {
++ static FILE *fp = (FILE *)NULL;
++ char buf[512]; /* XXX */
++ char profile[512]; /* XXX */
++ char *bp;
++ char *temp_home;
++ char *temp_path;
++
++ temp_home = (char *)getenv ("HOME");
++ if (!temp_home)
++ return ((char *)NULL);
++
++ strcpy (profile, temp_home);
++ strcat (profile, "/.mh_profile");
++
++ if (fp)
++ fclose (fp);
++
++ fp = fopen (profile, "r");
++ if (fp == (FILE *)NULL)
++ return ((char *)NULL);
++
++ while (fgets (buf, 512, fp) != (char *)NULL) /* XXX */
++ {
++ if ((bp = strstr (buf, "Path:")) != (char *)NULL)
++ {
++ bp += 5;
++ while (whitespace (*bp))
++ bp++;
++
++ if (*bp == '\0')
++ return ((char *)NULL);
++
++ temp_path = (char *)xmalloc (3 + strlen (bp) + strlen (temp_home));
++
++ strcpy (temp_path, temp_home);
++ strcat (temp_path, "/");
++ strcat (temp_path, bp);
++
++ bp = temp_path;
++
++ while (!(cr_whitespace (*bp)))
++ bp++;
++
++ *bp = '\0';
++
++ return temp_path;
++ }
++ }
++
++ return ((char *)NULL);
++ }
++
++ /* Expand FILENAME if it begins with a plus. This always returns
++ a new string. */
++ char *
++ plus_expand (filename)
++ char *filename;
++ {
++ static char *dirname = (char *)NULL;
++
++ if (filename && *filename == '+')
++ {
++ char *mh_path = get_mh_path ();
++
++ if (filename[1] == '/' || filename[1] == '.')
++ {
++ dirname = (char *)xmalloc (1 + strlen (filename));
++
++ strcpy(dirname, filename+1);
++
++ return dirname;
++ }
++
++ if (mh_path)
++ {
++ dirname = (char *)xmalloc (1 + strlen (filename) + strlen (mh_path));
++
++ strcpy (dirname, mh_path);
++ strcat (dirname, "/");
++ strcat (dirname, filename+1);
++
++ return dirname;
++ }
++ }
++ return (char *)NULL;
++ }
+
+
+ /*
+