]> git.ipfire.org Git - thirdparty/readline.git/commitdiff
basic code to handle lines longer than a screenful; fixes for printing variable value...
authorChet Ramey <chet.ramey@case.edu>
Wed, 16 Aug 2023 15:04:14 +0000 (11:04 -0400)
committerChet Ramey <chet.ramey@case.edu>
Wed, 16 Aug 2023 15:04:14 +0000 (11:04 -0400)
14 files changed:
bind.c
chardefs.h
complete.c
display.c
doc/history.3
doc/hsuser.texi
doc/readline.3
doc/rltech.texi
doc/rluser.texi
doc/version.texi
examples/fileman.c
m4/codeset.m4
readline.h
rltypedefs.h

diff --git a/bind.c b/bind.c
index ee6d6e1746eb8497108b82d95aff6f040c642206..3a44fefb97d186904280591a967e9ea9cc0f94e6 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -68,6 +68,9 @@ extern int errno;
 /* Variables exported by this file. */
 Keymap rl_binding_keymap;
 
+/* Functions exported by this file. */
+rl_macro_print_func_t *rl_macro_display_hook = (rl_macro_print_func_t *)NULL;
+
 static int _rl_skip_to_delim (char *, int, int);
 
 static void _rl_init_file_error (const char *, ...)  __attribute__((__format__ (printf, 1, 2)));
@@ -523,8 +526,7 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
 
   /* When there are incomplete prefixes \C- or \M- (has_control || has_meta)
      without base character at the end of SEQ, they are processed as the
-     prefixes for '\0'.
-  */
+     prefixes for '\0'. */
   for (i = l = 0; (c = seq[i]) || has_control || has_meta; i++)
     {
       /* Only backslashes followed by a non-null character are handled
@@ -621,11 +623,17 @@ rl_translate_keyseq (const char *seq, char *array, int *len)
          has_meta = 0;
        }
 
-      /* If convert-meta is turned on, convert a meta char to a key sequence  */
+      /* If convert-meta is turned on, convert a meta char to a key sequence */
       if (META_CHAR (c) && _rl_convert_meta_chars_to_ascii)
        {
-         array[l++] = ESC;     /* ESC is meta-prefix */
-         array[l++] = UNMETA (c);
+         int x = UNMETA (c);
+         if (x)
+           {
+             array[l++] = ESC; /* ESC is meta-prefix */
+             array[l++] = x;
+           }
+         else
+           array[l++] = c;     /* just do the best we can without sticking a NUL in there. */
        }
       else
        array[l++] = (c);
@@ -677,7 +685,8 @@ char *
 rl_untranslate_keyseq (int seq)
 {
   static char kseq[16];
-  int i, c;
+  int i;
+  unsigned char c;
 
   i = 0;
   c = seq;
@@ -688,35 +697,22 @@ rl_untranslate_keyseq (int seq)
       kseq[i++] = '-';
       c = UNMETA (c);
     }
-  else if (c == ESC)
+
+  if (c == ESC)
     {
       kseq[i++] = '\\';
       c = 'e';
     }
-  else if (CTRL_CHAR (c))
+  else if (CTRL_CHAR (c) || c == RUBOUT)
     {
       kseq[i++] = '\\';
       kseq[i++] = 'C';
       kseq[i++] = '-';
-      c = _rl_to_lower (UNCTRL (c));
-    }
-  else if (c == RUBOUT)
-    {
-      kseq[i++] = '\\';
-      kseq[i++] = 'C';
-      kseq[i++] = '-';
-      c = '?';
+      c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
     }
 
-  if (c == ESC)
-    {
-      kseq[i++] = '\\';
-      c = 'e';
-    }
-  else if (c == '\\' || c == '"')
-    {
-      kseq[i++] = '\\';
-    }
+  if (c == '\\' || c == '"')
+    kseq[i++] = '\\';
 
   kseq[i++] = (unsigned char) c;
   kseq[i] = '\0';
@@ -727,9 +723,9 @@ char *
 _rl_untranslate_macro_value (char *seq, int use_escapes)
 {
   char *ret, *r, *s;
-  int c;
+  unsigned char c;
 
-  r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
+  r = ret = (char *)xmalloc (8 * strlen (seq) + 1);
   for (s = seq; *s; s++)
     {
       c = *s;
@@ -740,7 +736,9 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
          *r++ = '-';
          c = UNMETA (c);
        }
-      else if (c == ESC)
+
+      /* We want to keep from printing literal control chars */
+      if (c == ESC)
        {
          *r++ = '\\';
          c = 'e';
@@ -765,15 +763,10 @@ _rl_untranslate_macro_value (char *seq, int use_escapes)
          c = '?';
        }
 
-      if (c == ESC)
-       {
-         *r++ = '\\';
-         c = 'e';
-       }
-      else if (c == '\\' || c == '"')
+      if (c == '\\' || c == '"')
        *r++ = '\\';
 
-      *r++ = (unsigned char)c;
+      *r++ = c;
     }
   *r = '\0';
   return ret;
@@ -2571,17 +2564,13 @@ _rl_get_keyname (int key)
   char *keyname;
   int i, c;
 
-  keyname = (char *)xmalloc (8);
+  keyname = (char *)xmalloc (9);
 
   c = key;
   /* Since this is going to be used to write out keysequence-function
      pairs for possible inclusion in an inputrc file, we don't want to
      do any special meta processing on KEY. */
 
-#if 1
-  /* XXX - Experimental */
-  /* We might want to do this, but the old version of the code did not. */
-
   /* If this is an escape character, we don't want to do any more processing.
      Just add the special ESC key sequence and return. */
   if (c == ESC)
@@ -2591,28 +2580,23 @@ _rl_get_keyname (int key)
       keyname[2] = '\0';
       return keyname;
     }
-#endif
 
-  /* RUBOUT is translated directly into \C-? */
-  if (key == RUBOUT)
+  if (key == ANYOTHERKEY)
     {
-      keyname[0] = '\\';
-      keyname[1] = 'C';
-      keyname[2] = '-';
-      keyname[3] = '?';
-      keyname[4] = '\0';
+      keyname[0] = '\0';
       return keyname;
     }
 
   i = 0;
+
   /* Now add special prefixes needed for control characters.  This can
      potentially change C. */
-  if (CTRL_CHAR (c))
+  if (CTRL_CHAR (c) || c == RUBOUT)
     {
       keyname[i++] = '\\';
       keyname[i++] = 'C';
       keyname[i++] = '-';
-      c = _rl_to_lower (UNCTRL (c));
+      c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
     }
 
   /* XXX experimental code.  Turn the characters that are not ASCII or
@@ -2690,53 +2674,24 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
          {
            char **seqs;
            register int i;
+           char *keyname;
+           size_t knlen;
 
            /* Find the list of keyseqs in this map which have FUNCTION as
               their target.  Add the key sequences found to RESULT. */
-           if (map[key].function)
-             seqs =
-               rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
-           else
+           if (map[key].function == 0)
              break;
 
+           seqs = rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
            if (seqs == 0)
              break;
 
+           keyname = _rl_get_keyname (key);
+           knlen = RL_STRLEN (keyname);
+
            for (i = 0; seqs[i]; i++)
              {
-               char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
-
-               if (key == ESC)
-                 {
-                   /* If ESC is the meta prefix and we're converting chars
-                      with the eighth bit set to ESC-prefixed sequences, then
-                      we can use \M-.  Otherwise we need to use the sequence
-                      for ESC. */
-                   if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
-                     sprintf (keyname, "\\M-");
-                   else
-                     sprintf (keyname, "\\e");
-                 }
-               else
-                 {
-                   int c = key, l = 0;
-                   if (CTRL_CHAR (c) || c == RUBOUT)
-                     {
-                       keyname[l++] = '\\';
-                       keyname[l++] = 'C';
-                       keyname[l++] = '-';
-                       c = (c == RUBOUT) ? '?' : _rl_to_lower (UNCTRL (c));
-                     }
-
-                   if (c == '\\' || c == '"')
-                     keyname[l++] = '\\';
-
-                   keyname[l++] = (char) c;
-                   keyname[l++] = '\0';
-                 }
-               
-               strcat (keyname, seqs[i]);
-               xfree (seqs[i]);
+               char *x;
 
                if (result_index + 2 > result_size)
                  {
@@ -2744,10 +2699,16 @@ rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
                    result = (char **)xrealloc (result, result_size * sizeof (char *));
                  }
 
-               result[result_index++] = keyname;
+               x = xmalloc (knlen + RL_STRLEN (seqs[i]) + 1);
+               strcpy (x, keyname);
+               strcpy (x + knlen, seqs[i]);
+               xfree (seqs[i]);
+
+               result[result_index++] = x;
                result[result_index] = (char *)NULL;
              }
 
+           xfree (keyname);
            xfree (seqs);
          }
          break;
@@ -2764,73 +2725,72 @@ rl_invoking_keyseqs (rl_command_func_t *function)
   return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
 }
 
-/* Print all of the functions and their bindings to rl_outstream.  If
-   PRINT_READABLY is non-zero, then print the output in such a way
-   that it can be read back in. */
 void
-rl_function_dumper (int print_readably)
+rl_print_keybinding (const char *name, Keymap kmap, int print_readably)
 {
-  register int i;
-  const char **names;
-  const char *name;
+  rl_command_func_t *function;
+  char **invokers;
 
-  names = rl_funmap_names ();
+  function = rl_named_function (name);
+  invokers = rl_invoking_keyseqs_in_map (function, kmap ? kmap : _rl_keymap);
 
-  fprintf (rl_outstream, "\n");
-
-  for (i = 0; name = names[i]; i++)
+  if (print_readably)
     {
-      rl_command_func_t *function;
-      char **invokers;
-
-      function = rl_named_function (name);
-      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
-
-      if (print_readably)
+      if (!invokers)
+       fprintf (rl_outstream, "# %s (not bound)\n", name);
+      else
        {
-         if (!invokers)
-           fprintf (rl_outstream, "# %s (not bound)\n", name);
-         else
-           {
-             register int j;
-
-             for (j = 0; invokers[j]; j++)
-               {
-                 fprintf (rl_outstream, "\"%s\": %s\n",
-                          invokers[j], name);
-                 xfree (invokers[j]);
-               }
+         register int j;
 
-             xfree (invokers);
+         for (j = 0; invokers[j]; j++)
+           {
+             fprintf (rl_outstream, "\"%s\": %s\n", invokers[j], name);
+             xfree (invokers[j]);
            }
+
+         xfree (invokers);
        }
+    }
+  else
+    {
+      if (!invokers)
+       fprintf (rl_outstream, "%s is not bound to any keys\n", name);
       else
        {
-         if (!invokers)
-           fprintf (rl_outstream, "%s is not bound to any keys\n",
-                    name);
-         else
-           {
-             register int j;
+         register int j;
 
-             fprintf (rl_outstream, "%s can be found on ", name);
+         fprintf (rl_outstream, "%s can be found on ", name);
 
-             for (j = 0; invokers[j] && j < 5; j++)
-               {
-                 fprintf (rl_outstream, "\"%s\"%s", invokers[j],
-                          invokers[j + 1] ? ", " : ".\n");
-               }
+         for (j = 0; invokers[j] && j < 5; j++)
+           fprintf (rl_outstream, "\"%s\"%s", invokers[j], invokers[j + 1] ? ", " : ".\n");
 
-             if (j == 5 && invokers[j])
-               fprintf (rl_outstream, "...\n");
+         if (j == 5 && invokers[j])
+           fprintf (rl_outstream, "...\n");
 
-             for (j = 0; invokers[j]; j++)
-               xfree (invokers[j]);
+         for (j = 0; invokers[j]; j++)
+           xfree (invokers[j]);
 
-             xfree (invokers);
-           }
+         xfree (invokers);
        }
     }
+}
+
+/* Print all of the functions and their bindings to rl_outstream.  If
+   PRINT_READABLY is non-zero, then print the output in such a way
+   that it can be read back in. */
+void
+rl_function_dumper (int print_readably)
+{
+  register int i;
+  const char **names;
+  const char *name;
+
+  names = rl_funmap_names ();
+
+  fprintf (rl_outstream, "\n");
+
+  for (i = 0; name = names[i]; i++)
+    rl_print_keybinding (name, _rl_keymap, print_readably);
 
   xfree (names);
 }
@@ -2863,6 +2823,16 @@ _rl_macro_dumper_internal (int print_readably, Keymap map, char *prefix)
          keyname = _rl_get_keyname (key);
          out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
 
+         /* If the application wants to print macros, let it. Give it the
+            ascii-fied value with backslash escapes, so it will have to use
+            rl_macro_bind (with its call to rl_translate_keyseq) to get the
+            same value back. */
+         if (rl_macro_display_hook)
+           {
+             (*rl_macro_display_hook) (keyname, out, print_readably, prefix);
+             break;
+           }
+
          if (print_readably)
            fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
                                                         keyname,
@@ -2926,10 +2896,40 @@ rl_dump_macros (int count, int key)
 static char *
 _rl_get_string_variable_value (const char *name)
 {
-  static char numbuf[32];
+  static char numbuf[64];
   char *ret;
 
-  if (_rl_stricmp (name, "bell-style") == 0)
+  if (_rl_stricmp (name, "active-region-start-color") == 0)
+    {
+      if (_rl_active_region_start_color == 0)
+       return 0;
+      ret = _rl_untranslate_macro_value (_rl_active_region_start_color, 0);
+      if (ret)
+       {
+         strncpy (numbuf, ret, sizeof (numbuf) - 1);
+         xfree (ret);
+         numbuf[sizeof(numbuf) - 1] = '\0';
+       }
+      else
+       numbuf[0] = '\0';
+      return numbuf;
+    }
+  else if (_rl_stricmp (name, "active-region-end-color") == 0)
+    {
+      if (_rl_active_region_end_color == 0)
+       return 0;
+      ret = _rl_untranslate_macro_value (_rl_active_region_end_color, 0);
+      if (ret)
+       {
+         strncpy (numbuf, ret, sizeof (numbuf) - 1);
+         xfree (ret);
+         numbuf[sizeof(numbuf) - 1] = '\0';
+       }
+      else
+       numbuf[0] = '\0';
+      return numbuf;
+    }
+  else if (_rl_stricmp (name, "bell-style") == 0)
     {
       switch (_rl_bell_preference)
        {
@@ -2963,7 +2963,7 @@ _rl_get_string_variable_value (const char *name)
     return (rl_get_keymap_name_from_edit_mode ());
   else if (_rl_stricmp (name, "history-size") == 0)
     {
-      sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0);
+      sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : -1);
       return (numbuf);
     }
   else if (_rl_stricmp (name, "isearch-terminators") == 0)
index 24a25f1f105bb45b41c8eefc5ad9b34d93aa941b..02f7e17e26927bdcc2b54393694a0a812967ff6c 100644 (file)
@@ -55,7 +55,7 @@
 #define largest_char 255                   /* Largest character value. */
 
 #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
-#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+#define META_CHAR(c) ((unsigned char)(c) > meta_character_threshold && (unsigned char)(c) <= largest_char)
 
 #define CTRL(c) ((c) & control_character_mask)
 #define META(c) ((c) | meta_character_bit)
index 349c87a1f0e19d3dbb6d39f0e211e87ee22c1523..9f170334efc16439197e89d4895c3e9e1fde0723 100644 (file)
@@ -2321,9 +2321,9 @@ rl_completion_matches (const char *text, rl_compentry_func_t *entry_function)
 char *
 rl_username_completion_function (const char *text, int state)
 {
-#if defined (_WIN32) || defined (__OPENNT)
+#if defined (_WIN32) || defined (__OPENNT) || !defined (HAVE_GETPWENT)
   return (char *)NULL;
-#else /* !_WIN32 && !__OPENNT) */
+#else /* !_WIN32 && !__OPENNT) && HAVE_GETPWENT */
   static char *username = (char *)NULL;
   static struct passwd *entry;
   static int namelen, first_char, first_char_loc;
@@ -2338,25 +2338,19 @@ rl_username_completion_function (const char *text, int state)
 
       username = savestring (&text[first_char_loc]);
       namelen = strlen (username);
-#if defined (HAVE_GETPWENT)
       setpwent ();
-#endif
     }
 
-#if defined (HAVE_GETPWENT)
   while (entry = getpwent ())
     {
       /* Null usernames should result in all users as possible completions. */
       if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
        break;
     }
-#endif
 
   if (entry == 0)
     {
-#if defined (HAVE_GETPWENT)
       endpwent ();
-#endif
       return ((char *)NULL);
     }
   else
@@ -2372,7 +2366,7 @@ rl_username_completion_function (const char *text, int state)
 
       return (value);
     }
-#endif /* !_WIN32 && !__OPENNT */
+#endif /* !_WIN32 && !__OPENNT && HAVE_GETPWENT */
 }
 
 /* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
@@ -2542,6 +2536,18 @@ rl_filename_completion_function (const char *text, int state)
        }
       filename_len = strlen (filename);
 
+      /* Normalize the filename if the application has set a rewrite hook. */
+      if (*filename && rl_filename_rewrite_hook)
+       {
+         temp = (*rl_filename_rewrite_hook) (filename, filename_len);
+         if (temp != filename)
+           {
+             xfree (filename);
+             filename = temp;
+             filename_len = strlen (filename);
+           }
+       }
+
       rl_filename_completion_desired = 1;
     }
 
@@ -2572,17 +2578,20 @@ rl_filename_completion_function (const char *text, int state)
       if (filename_len == 0)
        {
          if (_rl_match_hidden_files == 0 && HIDDEN_FILE (convfn))
-           continue;
+           {
+             if (convfn != dentry)
+               xfree (convfn);
+             continue;
+           }
 
          if (convfn[0] != '.' ||
               (convfn[1] && (convfn[1] != '.' || convfn[2])))
            break;
        }
-      else
-       {
-         if (complete_fncmp (convfn, convlen, filename, filename_len))
-           break;
-       }
+      else if (complete_fncmp (convfn, convlen, filename, filename_len))
+       break;
+      else if (convfn != dentry)
+       xfree (convfn);
     }
 
   if (entry == 0)
index b390fc9b110688a61faf604442fedc004b0015b3..feb46ef110d3fdd352dab6ea013fcc90126709f2 100644 (file)
--- a/display.c
+++ b/display.c
@@ -813,6 +813,7 @@ rl_redisplay (void)
   char *prompt_this_line;
   char cur_face;
   int hl_begin, hl_end;
+  int short_circuit;
   int mb_cur_max = MB_CUR_MAX;
 #if defined (HANDLE_MULTIBYTE)
   WCHAR_T wc;
@@ -1311,9 +1312,54 @@ rl_redisplay (void)
                norm_face (INV_LINE_FACE(linenum), INV_LLEN (linenum));
            }
 
+         /* XXX - experimental new code */
+         /* Now that _rl_last_v_pos is a logical count, not bounded by the
+            number of physical screen lines, this is a start at being able
+            to redisplay lines that consume more than the number of physical
+            screen lines in more than a simple `move-to-the-next-line' way.
+
+            If the new line has more lines than there are physical screen
+            lines, and the cursor would be off the top of the screen if we
+            displayed all the new lines, clear the screen without killing
+            the scrollback buffer, clear out the visible line so we do a
+            complete redraw, and make the loop break when we have displayed
+            a physical screen full of lines. Do the same if we are going to
+            move the cursor to a line that's greater than the number of
+            physical screen lines when we weren't before.
+
+            SHORT_CIRCUIT says where to break the loop. Pretty simple right now. */
+         short_circuit = -1;
+         if (inv_botlin >= _rl_screenheight)
+           {
+             int extra;
+
+             extra = inv_botlin - _rl_screenheight;    /* lines off the top */
+             /* cursor in portion of line that would be off screen or in
+                the lines that exceed the number of physical screen lines. */
+             if (cursor_linenum <= extra || 
+                  (cursor_linenum >= _rl_screenheight && _rl_vis_botlin <= _rl_screenheight))
+               {
+                 if (cursor_linenum <= extra)
+                   short_circuit = _rl_screenheight;
+                 _rl_clear_screen (0);
+                 if (visible_line)
+                   memset (visible_line, 0, line_size);
+                 rl_on_new_line ();
+               }
+             /* The cursor is beyond the number of lines that would be off
+                the top, but we still want to display only the first
+                _RL_SCREENHEIGHT lines starting at the beginning of the line. */
+             else if (cursor_linenum > extra && cursor_linenum <= _rl_screenheight &&
+                       _rl_vis_botlin <= _rl_screenheight)
+               short_circuit = _rl_screenheight;
+           }
+
          /* For each line in the buffer, do the updating display. */
          for (linenum = 0; linenum <= inv_botlin; linenum++)
            {
+             if (short_circuit >= 0 && linenum == short_circuit)
+               break;
+
              /* This can lead us astray if we execute a program that changes
                 the locale from a non-multibyte to a multibyte one. */
              o_cpos = _rl_last_c_pos;
@@ -1417,7 +1463,7 @@ rl_redisplay (void)
                    ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
                }
            }
-         _rl_vis_botlin = inv_botlin;
+         _rl_vis_botlin = (short_circuit >= 0) ? short_circuit : inv_botlin;
 
          /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
             different screen line during this redisplay. */
@@ -2748,8 +2794,6 @@ rl_on_new_line_with_prompt (void)
 int
 rl_forced_update_display (void)
 {
-  register char *temp;
-
   if (visible_line)
     memset (visible_line, 0, line_size);
 
@@ -2934,9 +2978,25 @@ _rl_move_vert (int to)
 {
   register int delta, i;
 
-  if (_rl_last_v_pos == to || to > _rl_screenheight)
+  if (_rl_last_v_pos == to)
     return;
 
+#if 0
+  /* If we're being asked to move to a line beyond the screen height, and
+     we're currently at the last physical line, issue a newline and let the
+     terminal take care of scrolling the display. */
+  if (to >= _rl_screenheight)
+    {
+      if (_rl_last_v_pos == _rl_screenheight)
+       {
+         putc ('\n', rl_outstream);
+         _rl_cr ();
+         _rl_last_c_pos = 0;
+       }
+      return;
+    }
+#endif
+
   if ((delta = to - _rl_last_v_pos) > 0)
     {
       for (i = 0; i < delta; i++)
index 082bf42d6fe82c01d65605fb3593e07ea2353e9c..63a40049dab57129f256d9cf05edde5f0b57156e 100644 (file)
@@ -119,13 +119,13 @@ is followed immediately by a newline.
 If \fIstring\fP is missing, the string from the most recent search is used;
 it is an error if there is no previous search string.
 .TP
-.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u
+.B \d\s+2\(ha\s-2\u\fIstring1\fP\d\s+2\(ha\s-2\u\fIstring2\fP\d\s+2\(ha\s-2\u
 Quick substitution.  Repeat the last command, replacing
 .I string1
 with
 .IR string2 .
 Equivalent to
-``!!:s\d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u''
+``!!:s\d\s+2\(ha\s-2\u\fIstring1\fP\d\s+2\(ha\s-2\u\fIstring2\fP\d\s+2\(ha\s-2\u''
 (see \fBModifiers\fP below).
 .TP
 .B !#
@@ -137,7 +137,7 @@ A
 .B :
 separates the event specification from the word designator.
 It may be omitted if the word designator begins with a
-.BR ^ ,
+.BR \(ha ,
 .BR $ ,
 .BR * ,
 .BR \- ,
@@ -156,7 +156,7 @@ word.
 .I n
 The \fIn\fRth word.
 .TP
-.B ^
+.B \(ha
 The first argument.  That is, word 1.
 .TP
 .B $
@@ -497,7 +497,7 @@ This section documents the functions for managing a history file.
 
 .Fn1 int read_history "const char *filename"
 Add the contents of \fIfilename\fP to the history list, a line at a time.
-If \fIfilename\fP is \fBNULL\fP, then read from \fI~/.history\fP.
+If \fIfilename\fP is \fBNULL\fP, then read from \fI\(ti/.history\fP.
 Returns 0 if successful, or \fBerrno\fP if not.
 
 .Fn3 int read_history_range "const char *filename" "int from" "int to"
@@ -505,25 +505,25 @@ Read a range of lines from \fIfilename\fP, adding them to the history list.
 Start reading at line \fIfrom\fP and end at \fIto\fP.
 If \fIfrom\fP is zero, start at the beginning.  If \fIto\fP is less than
 \fIfrom\fP, then read until the end of the file.  If \fIfilename\fP is
-\fBNULL\fP, then read from \fI~/.history\fP.  Returns 0 if successful,
+\fBNULL\fP, then read from \fI\(ti/.history\fP.  Returns 0 if successful,
 or \fBerrno\fP if not.
 
 .Fn1 int write_history "const char *filename"
 Write the current history to \fIfilename\fP, overwriting \fIfilename\fP
 if necessary.
-If \fIfilename\fP is \fBNULL\fP, then write the history list to \fI~/.history\fP.
+If \fIfilename\fP is \fBNULL\fP, then write the history list to \fI\(ti/.history\fP.
 Returns 0 on success, or \fBerrno\fP on a read or write error.
 
 
 .Fn2 int append_history "int nelements" "const char *filename"
 Append the last \fInelements\fP of the history list to \fIfilename\fP.
-If \fIfilename\fP is \fBNULL\fP, then append to \fI~/.history\fP.
+If \fIfilename\fP is \fBNULL\fP, then append to \fI\(ti/.history\fP.
 Returns 0 on success, or \fBerrno\fP on a read or write error.
 
 .Fn2 int history_truncate_file "const char *filename" "int nlines"
 Truncate the history file \fIfilename\fP, leaving only the last
 \fInlines\fP lines.
-If \fIfilename\fP is \fBNULL\fP, then \fI~/.history\fP is truncated.
+If \fIfilename\fP is \fBNULL\fP, then \fI\(ti/.history\fP is truncated.
 Returns 0 on success, or \fBerrno\fP on failure.
 
 .SS History Expansion
@@ -604,7 +604,7 @@ Setting this to 0 inhibits history expansion.
 
 .Vb char history_subst_char
 The character that invokes word substitution if found at the start of
-a line.  The default is \fB^\fP.
+a line.  The default is \fB\(ha\fP.
 
 .Vb char history_comment_char
 During tokenization, if this character is seen as the first character
@@ -643,7 +643,7 @@ By default, this variable is set to \fBNULL\fP.
 .SH FILES
 .PD 0 
 .TP
-.FN ~/.history
+.FN \(ti/.history
 Default filename for reading and writing saved history
 .PD
 .SH "SEE ALSO"
index 9081baf8bd205c55091c00911fb9acb234857005..177114078ce42edee2826a91abfded9664028632 100644 (file)
@@ -90,8 +90,8 @@ named by @env{$HISTFILE}.
 If the @code{histappend} shell option is set (@pxref{Bash Builtins}),
 the lines are appended to the history file,
 otherwise the history file is overwritten.
-If @env{HISTFILE}
-is unset, or if the history file is unwritable, the history is not saved.
+If @env{HISTFILE} is unset or null,
+or if the history file is unwritable, the history is not saved.
 After saving the history, the history file is truncated
 to contain no more than @env{$HISTFILESIZE} lines.
 If @env{HISTFILESIZE} is unset, or set to null, a non-numeric value, or
@@ -104,7 +104,7 @@ When the history file is read, lines beginning with the history
 comment character followed immediately by a digit are interpreted
 as timestamps for the following history entry.
 
-The builtin command @code{fc} may be used to list or edit and re-execute
+The @code{fc} builtin command may be used to list or edit and re-execute
 a portion of the history list.
 The @code{history} builtin may be used to display or modify the history
 list and manipulate the history file.
@@ -113,8 +113,9 @@ are available in each editing mode that provide access to the
 history list (@pxref{Commands For History}).
 
 The shell allows control over which commands are saved on the history
-list.  The @env{HISTCONTROL} and @env{HISTIGNORE}
-variables may be set to cause the shell to save only a subset of the
+list.
+The @env{HISTCONTROL} and @env{HISTIGNORE}
+variables are used to cause the shell to save only a subset of the
 commands entered.
 The @code{cmdhist}
 shell option, if enabled, causes the shell to attempt to save each
@@ -250,6 +251,7 @@ If a @var{filename} argument is supplied
 when any of the @option{-w}, @option{-r}, @option{-a}, or @option{-n} options
 is used, Bash uses @var{filename} as the history file.
 If not, then the value of the @env{HISTFILE} variable is used.
+If @env{HISTFILE} is unset or null, these options have no effect.
 
 The return value is 0 unless an invalid option is encountered, an
 error occurs while reading or writing the history file, an invalid
@@ -282,14 +284,21 @@ expansion functions about quoting still in effect from previous lines.
 History expansion takes place in two parts.  The first is to determine
 which line from the history list should be used during substitution.
 The second is to select portions of that line for inclusion into the
-current one.  The line selected from the history is called the
-@dfn{event}, and the portions of that line that are acted upon are
-called @dfn{words}.  Various @dfn{modifiers} are available to manipulate
-the selected words.  The line is broken into words in the same fashion
+current one.
+
+The line selected from the history is called the @dfn{event},
+and the portions of that line that are acted upon are called @dfn{words}.
+The dfn{event designator} selects the event, the optional
+@dfn{word designator} selects words from the event, and
+various optional @dfn{modifiers} are available to manipulate the
+selected words.
+
+The line is broken into words in the same fashion
 that Bash does, so that several words
 surrounded by quotes are considered one word.
 History expansions are introduced by the appearance of the
 history expansion character, which is @samp{!} by default.
+History expansions may appear anywhere in the input, but do not nest.
 
 History expansion implements shell-like quoting conventions:
 a backslash can be used to remove the special handling for the next character;
@@ -347,6 +356,9 @@ An event designator is a reference to a command line entry in the
 history list.
 Unless the reference is absolute, events are relative to the current
 position in the history list.
+The event designator consists of the portion of the word beginning
+with the history expansion character, and ending with the word designator
+if one is present, or the end of the word.
 @cindex history events
 
 @table @asis
@@ -354,8 +366,9 @@ position in the history list.
 @item @code{!}
 @ifset BashFeatures
 Start a history substitution, except when followed by a space, tab,
-the end of the line, @samp{=} or @samp{(} (when the
-@code{extglob} shell option is enabled using the @code{shopt} builtin).
+the end of the line, @samp{=},
+or the rest of the shell metacharacters defined above
+(@pxref{Definitions}).
 @end ifset
 @ifclear BashFeatures
 Start a history substitution, except when followed by a space, tab,
@@ -400,6 +413,8 @@ The entire command line typed so far.
 @subsection Word Designators
 
 Word designators are used to select desired words from the event.
+They are optional; if the word designator isn't supplied, the history
+expansion uses the entire event.
 A @samp{:} separates the event specification from the word designator.  It
 may be omitted if the word designator begins with a @samp{^}, @samp{$},
 @samp{*}, @samp{-}, or @samp{%}.  Words are numbered from the beginning
index 9a63e09e42a1479d0c4af6866c468cccf10f411c..8b0ba10861dcfcd21b0cb360910af5164864e7c7 100644 (file)
@@ -6,9 +6,9 @@
 .\"    Case Western Reserve University
 .\"    chet.ramey@case.edu
 .\"
-.\"    Last Change: Fri Feb 17 10:59:58 EST 2023
+.\"    Last Change: Mon Jul 17 16:46:23 EDT 2023
 .\"
-.TH READLINE 3 "2023 February 17" "GNU Readline 8.2"
+.TH READLINE 3 "2023 July 17" "GNU Readline 8.3"
 .\"
 .\" File Name macro.  This used to be `.PN', for Path Name,
 .\" but Sun doesn't seem to like that very much.
@@ -116,7 +116,7 @@ file (the \fIinputrc\fP file).
 The name of this file is taken from the value of the
 .B INPUTRC
 environment variable.  If that variable is unset, the default is
-.IR ~/.inputrc .
+.IR \(ti/.inputrc .
 If that file  does not exist or cannot be read, the ultimate default is
 .IR /etc/inputrc .
 When a program which uses the readline library starts up, the
@@ -215,7 +215,7 @@ are not recognized.
 .br
 "\eC\-x\eC\-r": re\-read\-init\-file
 .br
-"\ee[11~": "Function Key 1"
+"\ee[11\(ti": "Function Key 1"
 .RE
 .PP
 In this example,
@@ -226,7 +226,7 @@ is again bound to the function
 is bound to the function
 .BR re\-read\-init\-file ,
 and
-.I "ESC [ 1 1 ~"
+.I "ESC [ 1 1 \(ti"
 is bound to insert the text
 .if t \f(CWFunction Key 1\fP.
 .if n ``Function Key 1''.
@@ -371,8 +371,12 @@ If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
 .TP
 .B bind\-tty\-special\-chars (On)
 If set to \fBOn\fP (the default), readline attempts to bind the control
-characters   treated specially by the kernel's terminal driver to their
+characters that are
+treated specially by the kernel's terminal driver to their
 readline equivalents.
+These override the default readline bindings described here.
+Type \f(CWstty -a\fP at a bash prompt to see your current terminal settings,
+including the special control characters (usually \fBcchars\fP).
 .TP
 .B blink\-matching\-paren (Off)
 If set to \fBOn\fP, readline attempts to briefly move the cursor to an
@@ -1152,7 +1156,7 @@ The actual completion performed is application-specific.
 .BR Bash ,
 for instance, attempts completion treating the text as a variable
 (if the text begins with \fB$\fP), username (if the text begins with
-\fB~\fP), hostname (if the text begins with \fB@\fP), or
+\fB\(ti\fP), hostname (if the text begins with \fB@\fP), or
 command (including aliases and functions) in turn.  If none
 of these produces a match, filename completion is attempted.
 .BR Gdb ,
@@ -1384,7 +1388,7 @@ Emacs Standard bindings
 "C-_"  undo
 "\^ " to "/"  self-insert
 "0"  to "9"  self-insert
-":"  to "~"  self-insert
+":"  to "\(ti"  self-insert
 "C-?"  backward-delete-char
 .PP
 Emacs Meta bindings
@@ -1431,7 +1435,7 @@ Emacs Meta bindings
 "M-U"  upcase-word
 "M-Y"  yank-pop
 "M-\e"  delete-horizontal-space
-"M-~"  tilde-expand
+"M-\(ti"  tilde-expand
 "M-C-?"  backward-kill-word
 "M-_"  yank-last-arg
 .PP
@@ -1469,7 +1473,7 @@ VI Insert Mode functions
 "C-Y"  yank
 "C-["  vi-movement-mode
 "C-_"  undo
-"\^ " to "~"  self-insert
+"\^ " to "\(ti"  self-insert
 "C-?"  backward-delete-char
 .PP
 VI Command Mode functions
@@ -1527,7 +1531,7 @@ VI Command Mode functions
 "X"  backward-delete-char
 "Y"  vi-yank-to
 "\e"  vi-complete
-"^"  vi-first-print
+"\(ha"  vi-first-print
 "_"  vi-yank-arg
 "`"  vi-goto-mark
 "a"  vi-append-mode
@@ -1552,7 +1556,7 @@ VI Command Mode functions
 "x"  vi-delete
 "y"  vi-yank-to
 "|"  vi-column
-"~"  vi-change-case
+"\(ti"  vi-change-case
 .RE
 .SH "SEE ALSO"
 .PD 0
@@ -1566,7 +1570,7 @@ VI Command Mode functions
 .SH FILES
 .PD 0
 .TP
-.FN ~/.inputrc
+.FN \(ti/.inputrc
 Individual \fBreadline\fP initialization file
 .PD
 .SH AUTHORS
index 4d3f3ccacd68768d797458bfce9242f77723118a..c83d99d51a481602974f7a3842a20ccc566642c2 100644 (file)
@@ -515,6 +515,15 @@ By default, this is set to @code{rl_deprep_terminal}
 (@pxref{Terminal Management}).
 @end deftypevar
 
+@deftypevar {void} rl_macro_display_hook 
+If set, this points to a function that @code{rl_macro_dumper} will call to
+display a key sequence bound to a macro.
+It is called with the key sequence, the "untranslated" macro value (i.e.,
+with backslash escapes included, as when passed to @code{rl_macro_bind}),
+the @code{readable} argument passed to @code{rl_macro_dumper}, and any
+prefix to display before the key sequence.
+@end deftypevar
+
 @deftypevar {Keymap} rl_executing_keymap
 This variable is set to the keymap (@pxref{Keymaps}) in which the
 currently executing Readline function was found.
@@ -917,9 +926,19 @@ Return an array of strings representing the key sequences used to
 invoke @var{function} in the keymap @var{map}.
 @end deftypefun
 
+@deftypefun void rl_print_keybinding (const char *name, Keymap map, int readable)
+Print key sequences bound to Readline function name @var{name} in
+keymap @var{map}.
+If @var{map} is NULL, this uses the current keymap.
+If @var{readable} is non-zero,
+the list is formatted in such a way that it can be made part of an
+@code{inputrc} file and re-read.
+@end deftypefun
+
 @deftypefun void rl_function_dumper (int readable)
 Print the Readline function names and the key sequences currently
-bound to them to @code{rl_outstream}.  If @var{readable} is non-zero,
+bound to them to @code{rl_outstream}.
+If @var{readable} is non-zero,
 the list is formatted in such a way that it can be made part of an
 @code{inputrc} file and re-read.
 @end deftypefun
@@ -1348,14 +1367,17 @@ If @var{c} is a number, return the value it represents.
 Bind the key sequence @var{keyseq} to invoke the macro @var{macro}.
 The binding is performed in @var{map}.  When @var{keyseq} is invoked, the
 @var{macro} will be inserted into the line.  This function is deprecated;
-use @code{rl_generic_bind()} instead.
+use @code{rl_generic_bind} instead.
 @end deftypefun
 
 @deftypefun void rl_macro_dumper (int readable)
 Print the key sequences bound to macros and their values, using
 the current keymap, to @code{rl_outstream}.
-If @var{readable} is non-zero, the list is formatted in such a way
+If the application has assigned a value to @code{rl_macro_display_hook},
+@code{rl_macro_dumper} calls it instead of printing anything.
+If @var{readable} is greater than zero, the list is formatted in such a way
 that it can be made part of an @code{inputrc} file and re-read.
+
 @end deftypefun
 
 @deftypefun int rl_variable_bind (const char *variable, const char *value)
index 5e8a36af205cb7c4cd49f9d4740d7f8a61ef727d..a0cf21c805ceb8e7785d66118d87767f6f62a205 100644 (file)
@@ -456,8 +456,12 @@ the terminal's bell.
 @item bind-tty-special-chars
 @vindex bind-tty-special-chars
 If set to @samp{on} (the default), Readline attempts to bind the control
-characters   treated specially by the kernel's terminal driver to their
+characters that are
+treated specially by the kernel's terminal driver to their
 Readline equivalents.
+These override the default Readline bindings described here.
+Type @samp{stty -a} at a Bash prompt to see your current terminal settings,
+including the special control characters (usually @code{cchars}).
 
 @item blink-matching-paren
 @vindex blink-matching-paren
@@ -1464,6 +1468,16 @@ moving point past that word as well.
 If the insertion point is at the end of the line, this transposes
 the last two words on the line.
 
+@ifset BashFeatures
+@item shell-transpose-words (M-C-t)
+Drag the word before point past the word after point,
+moving point past that word as well.
+If the insertion point is at the end of the line, this transposes
+the last two words on the line.
+Word boundaries are the same as @code{shell-forward-word} and
+@code{shell-backward-word}.
+@end ifset
+
 @item upcase-word (M-u)
 Uppercase the current (or following) word.  With a negative argument,
 uppercase the previous word, but do not move the cursor.
@@ -1534,14 +1548,6 @@ Kill the word behind point.
 Word boundaries are the same as @code{shell-backward-word}.
 @end ifset
 
-@item shell-transpose-words (M-C-t)
-Drag the word before point past the word after point,
-moving point past that word as well.
-If the insertion point is at the end of the line, this transposes
-the last two words on the line.
-Word boundaries are the same as @code{shell-forward-word} and
-@code{shell-backward-word}.
-
 @item unix-word-rubout (C-w)
 Kill the word behind point, using white space as a word boundary.
 The killed text is saved on the kill-ring.
index e117043dca11cacbf8c09ea8ba1f2f0f963f00ec..19dfe9a27b992f6f1fc16506a11541316fe0e095 100644 (file)
@@ -2,10 +2,10 @@
 Copyright (C) 1988-2023 Free Software Foundation, Inc. 
 @end ignore
 
-@set EDITION 8.2
-@set VERSION 8.2
+@set EDITION 8.3
+@set VERSION 8.3
 
-@set UPDATED 15 June 2023
-@set UPDATED-MONTH June 2023
+@set UPDATED 31 July 2023
+@set UPDATED-MONTH July 2023
 
-@set LASTCHANGE Thu Jun 15 14:37:40 EDT 2023
+@set LASTCHANGE Mon Jul 31 10:09:09 EDT 2023
index df579450deb1423a42e126e37e1c8214b6ec3798..c26bccf099be81a5e9cd70cefa3082ddb8c2c2fb 100644 (file)
@@ -286,8 +286,7 @@ static char syscom[1024];
 
 /* List the file(s) named in arg. */
 int
-com_list (arg)
-     char *arg;
+com_list (char *arg)
 {
   if (!arg)
     arg = "";
@@ -297,8 +296,7 @@ com_list (arg)
 }
 
 int
-com_view (arg)
-     char *arg;
+com_view (char *arg)
 {
   if (!valid_argument ("view", arg))
     return 1;
@@ -313,16 +311,14 @@ com_view (arg)
 }
 
 int
-com_rename (arg)
-     char *arg;
+com_rename (char *arg)
 {
   too_dangerous ("rename");
   return (1);
 }
 
 int
-com_stat (arg)
-     char *arg;
+com_stat (char *arg)
 {
   struct stat finfo;
 
@@ -350,8 +346,7 @@ com_stat (arg)
 }
 
 int
-com_delete (arg)
-     char *arg;
+com_delete (char *arg)
 {
   too_dangerous ("delete");
   return (1);
@@ -360,8 +355,7 @@ com_delete (arg)
 /* Print out help for ARG, or for all of the commands if ARG is
    not present. */
 int
-com_help (arg)
-     char *arg;
+com_help (char *arg)
 {
   register int i;
   int printed = 0;
@@ -400,8 +394,7 @@ com_help (arg)
 
 /* Change to the directory ARG. */
 int
-com_cd (arg)
-     char *arg;
+com_cd (char *arg)
 {
   if (chdir (arg) == -1)
     {
@@ -415,8 +408,7 @@ com_cd (arg)
 
 /* Print out the current working directory. */
 int
-com_pwd (ignore)
-     char *ignore;
+com_pwd (char *ignore)
 {
   char dir[1024], *s;
 
@@ -433,8 +425,7 @@ com_pwd (ignore)
 
 /* The user wishes to quit using this program.  Just set DONE non-zero. */
 int
-com_quit (arg)
-     char *arg;
+com_quit (char *arg)
 {
   done = 1;
   return (0);
@@ -442,8 +433,7 @@ com_quit (arg)
 
 /* Function which tells you that you can't do this. */
 void
-too_dangerous (caller)
-     char *caller;
+too_dangerous (char *caller)
 {
   fprintf (stderr,
            "%s: Too dangerous for me to distribute.  Write it yourself.\n",
@@ -453,8 +443,7 @@ too_dangerous (caller)
 /* Return non-zero if ARG is a valid argument for CALLER, else print
    an error message and return zero. */
 int
-valid_argument (caller, arg)
-     char *caller, *arg;
+valid_argument (char *caller, char *arg)
 {
   if (!arg || !*arg)
     {
index 280f556fe83dfb4ac832f8533cfc5610feb57275..eb7326013d3091b72af3d7fb3f73ae38820ef820 100644 (file)
@@ -1,5 +1,5 @@
 # codeset.m4 serial 5 (gettext-0.18.2)
-dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019 Free Software
+dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019-2022 Free Software
 dnl Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
index 5b83d29eb87bacb2ce51e5f9a3d0b6cf209fcc60..828a42a626a6170fbc4a07080d61011002720eba 100644 (file)
@@ -341,7 +341,9 @@ extern int rl_trim_arg_from_keyseq (const char *, size_t, Keymap);
 extern void rl_list_funmap_names (void);
 extern char **rl_invoking_keyseqs_in_map (rl_command_func_t *, Keymap);
 extern char **rl_invoking_keyseqs (rl_command_func_t *);
+
+extern void rl_print_keybinding (const char *, Keymap, int);
+
 extern void rl_function_dumper (int);
 extern void rl_macro_dumper (int);
 extern void rl_variable_dumper (int);
@@ -623,6 +625,8 @@ extern rl_voidfunc_t *rl_redisplay_function;
 extern rl_vintfunc_t *rl_prep_term_function;
 extern rl_voidfunc_t *rl_deprep_term_function;
 
+extern rl_macro_print_func_t *rl_macro_display_hook;
+
 /* Dispatch variables. */
 extern Keymap rl_executing_keymap;
 extern Keymap rl_binding_keymap;
index d179e858f17605d2eaaf2413f821258db3cd6ceb..61b81316502c8b37569c0b50c3dfbfe79760d1c5 100644 (file)
@@ -57,6 +57,9 @@ typedef int rl_compignore_func_t (char **);
 
 typedef void rl_compdisp_func_t (char **, int, int);
 
+/* Functions for displaying key bindings. Currently only one. */
+typedef void rl_macro_print_func_t (const char *, const char *, int, const char *);
+
 /* Type for input and pre-read hook functions like rl_event_hook */
 typedef int rl_hook_func_t (void);