bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

patch submission: "read -i" feature


From: Kevin Pulo
Subject: patch submission: "read -i" feature
Date: Tue, 18 Jul 2006 14:03:56 +1000
User-agent: Mutt/1.5.3i

Hi,

This patch for bash 3.1 adds a "-i" option to the read builtin.  When
this option is present and readline is being used (ie. -e also
specified), it specifies the "initial text", which is placed into the
readline edit buffer.  This allows a "default" value to be
automatically included on the user's edit line - if the user just
presses Enter, then that value will be put into $REPLY, otherwise the
user can edit the value before pressing Enter.

An example of the usefulness of this is when renaming files.  I find
that frequently when I am renaming files, the new name closely
resembles the old name.  Eg. adding ".old" to the end, adding "new_"
to the front, etc.  I have the following function in my .bash_profile:

        function rnm {
                local newname
                if [ $# = 1 ]; then
                        read -e -p "New filename: " -i "$1" newname
                        mv -i "$1" "$newname"
                else
                        mv -i "$@"
                fi
        }
        export -f rnm

This lets me rename files very easily:

        bash-3.1$ rnm somefile.txt
        New filename: somefile.txt

Now I can type ".old<Enter>", or "^Anew_<Enter>", or perhaps even
"^A<RightArrow*4>other<Enter>", and so on.  Without the -i option to
read, I have to spell out both the old and new filenames in the mv
command.  Even with tab completion, if the filenames are long and in a
directory with many similarly-named files, this can be tedious.

I'm sure that there are potentially other uses for this option.  The
patch is fairly straightforward and unintrusive.  I'd appreciate any
feedback on it.

Thanks.

Kev.

--- bash-3.1/builtins/read.def  2005-08-21 11:46:19.000000000 +1000
+++ bash-3.1kp1/builtins/read.def       2006-07-18 14:00:00.000000000 +1000
@@ -23,7 +23,7 @@
 
 $BUILTIN read
 $FUNCTION read_builtin
-$SHORT_DOC read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] 
[-d delim] [name ...]
+$SHORT_DOC read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] 
[-d delim] [-i initial] [name ...]
 One line is read from the standard input, or from file descriptor FD if the
 -u option is supplied, and the first word is assigned to the first NAME,
 the second word to the second NAME, and so on, with leftover words assigned
@@ -38,7 +38,9 @@
 the shell is interactive, readline is used to obtain the line.  If -n is
 supplied with a non-zero NCHARS argument, read returns after NCHARS
 characters have been read.  The -s option causes input coming from a
-terminal to not be echoed.
+terminal to not be echoed.  If the -i option is given and readline is being
+used, the string following it is the `default' or `initial' string that is
+placed into the edit buffer prior to obtaining the user's input.
 
 The -t option causes read to time out and return failure if a complete line
 of input is not read within TIMEOUT seconds.  If the TMOUT variable is set,
@@ -90,7 +92,7 @@
 extern int interrupt_immediately;
 
 #if defined (READLINE)
-static char *edit_line __P((char *));
+static char *edit_line __P((char *, char *));
 static void set_eol_delim __P((int));
 static void reset_eol_delim __P((char *));
 #endif
@@ -134,7 +136,7 @@
   unsigned int tmout;
   intmax_t intval;
   char c;
-  char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
+  char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname, 
*initial;
   char *e, *t, *t1;
   struct stat tsb;
   SHELL_VAR *var;
@@ -159,6 +161,7 @@
   USE_VAR(ifs_chars);
   USE_VAR(prompt);
   USE_VAR(arrayname);
+  USE_VAR(initial);
 #if defined (READLINE)
   USE_VAR(rlbuf);
   USE_VAR(rlind);
@@ -168,7 +171,7 @@
   i = 0;               /* Index into the string that we are reading. */
   raw = edit = 0;      /* Not reading raw input by default. */
   silent = 0;
-  arrayname = prompt = (char *)NULL;
+  arrayname = prompt = initial = (char *)NULL;
   fd = 0;              /* file descriptor to read from */
 
 #if defined (READLINE)
@@ -181,7 +184,7 @@
   delim = '\n';                /* read until newline */
 
   reset_internal_getopt ();
-  while ((opt = internal_getopt (list, "ersa:d:n:p:t:u:")) != -1)
+  while ((opt = internal_getopt (list, "ersa:d:n:p:i:t:u:")) != -1)
     {
       switch (opt)
        {
@@ -191,6 +194,9 @@
        case 'p':
          prompt = list_optarg;
          break;
+       case 'i':
+         initial = list_optarg;
+         break;
        case 's':
          silent = 1;
          break;
@@ -294,7 +300,7 @@
      terminal, turn them off. */
   if ((prompt || edit || silent) && input_is_tty == 0)
     {
-      prompt = (char *)NULL;
+      prompt = initial = (char *)NULL;
       edit = silent = 0;
     }
 
@@ -394,7 +400,7 @@
            }
          if (rlbuf == 0)
            {
-             rlbuf = edit_line (prompt ? prompt : "");
+             rlbuf = edit_line (prompt ? prompt : "", initial);
              rlind = 0;
            }
          if (rlbuf == 0)
@@ -689,10 +695,31 @@
 
 #if defined (READLINE)
 static rl_completion_func_t *old_attempted_completion_function;
+static rl_hook_func_t *old_startup_hook;
+static char *initial_text;
+
+int
+set_initial_text (void)
+{
+  int rc1, rc2;
+
+  rc1 = rc2 = 0;
+  if (old_startup_hook)
+    rc1 = (*old_startup_hook)();
+  if (initial_text)
+    {
+      rc2 = rl_insert_text(initial_text);
+      initial_text = (char *)NULL;
+      rl_startup_hook = old_startup_hook;
+      old_startup_hook = (rl_hook_func_t *)NULL;
+    }
+  return rc1 || rc2;
+}
 
 static char *
-edit_line (p)
+edit_line (p, i)
      char *p;
+     char *i;
 {
   char *ret;
   int len;
@@ -701,6 +728,12 @@
     initialize_readline ();
   old_attempted_completion_function = rl_attempted_completion_function;
   rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+  if (i)
+    {
+      old_startup_hook = rl_startup_hook;
+      rl_startup_hook = set_initial_text;
+      initial_text = i;
+    }
   ret = readline (p);
   rl_attempted_completion_function = old_attempted_completion_function;
   if (ret == 0)




-- 
.----------------------------------------------------------------------.
| Kevin Pulo                Quidquid latine dictum sit, altum viditur. |
| address@hidden               _ll l_ng__g_e_ _r_ hi__ly p__d_ct__le. |
| http://www.kev.pulo.com.au/         God casts the die, not the dice. |
`--------------- Linux: The choice of a GNU generation. ---------------'




reply via email to

[Prev in Thread] Current Thread [Next in Thread]