bind -X shows inactive bindings (bindings removed using bind -r)
Hi, according to `bind --help`, `bind -X` should "List key sequences bound with -x and associated commands in a form that can be reused as input.". However, when I remove a binding using `bind -r` it still shows up in the list. Reproduce: 1) Bind command using: `bind -x "\"\C-r\":\"echo I just pressed C-R\""` Everything works as expected. Pressing `\C-r` runs `echo I just pressed C-R`. Running `bind -X` shows the following list of bound commands: `"\C-r": "echo I just pressed C-R"` 2) Unbind command using `bind -r "\C-r"` Pressing `\C-r` does nothing as expected. Running `bind -X` still shows the same list of bound commands: `"\C-r": "echo I just pressed C-R"` This behavior seems very weird to me. I would expect the binding list to match actual active bindings. Affected bash versions: 4.3 - 5.0.11 Best regards, Simon Let
Re: bind -X shows inactive bindings (bindings removed using bind -r)
> according to `bind --help`, `bind -X` should "List key sequences bound with > -x and associated commands in a form that can be reused as input.". > > However, when I remove a binding using `bind -r` it still shows up in the > list. > > Simon Let I also would like to see this problem fixed. In this February, I actually posted to this mailing list a patch fixing this problem (with another patch): https://lists.gnu.org/archive/html/bug-bash/2019-02/msg00038.html Although the first patch was applied to the devel branch, the second one which fixes this problem seems not to have been reviewed yet. I updated the patch to fit the current devel branch. I attach the updated patch. Here is the description quoted from the mail: > In the second patch > `0002-do-not-print-unbound-bindings-in-bind-X.patch', to correctly > dump `bind -x' bindings, I created a new function > `_print_unix_command_map_internal' by modifying > `_rl_macro_dumper_internal' (lib/readline/bind.c). However, the > implementation of `_print_unix_command_map_internal' uses private > readline functions `_rl_get_keyname' and > `_rl_untranslate_macro_value', so the implementation should be > modified somehow or maybe these private functions can be made > public. Note that in the attached patch the functions in Readline library, `_rl_get_keyname' and `_rl_untranslate_macro_value', were made public and used from Bash codes. I think it is worth to make them a part of public interface of Readline library. Even if Chet does not use my patch and instead write a new code with another approach for this, I am anyway happy as far as the problem is fixed. Best regards, Koichi From 9eddd581f385712238bdbd146eeca261960592a2 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 11 Feb 2019 19:23:09 +0900 Subject: [PATCH] do not print unbound bindings in "bind -X" --- bashline.c | 73 + lib/readline/bind.c | 2 +- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/bashline.c b/bashline.c index e992c64b..040946e2 100644 --- a/bashline.c +++ b/bashline.c @@ -4368,16 +4368,77 @@ bash_execute_unix_command (count, key) return 0; } +static void +_print_unix_command_map_internal (Keymap map, Keymap xmap, char *prefix) +{ + register int key; + char *keyname, *out; + int prefix_len; + + /* XXX - They are private readline functions... */ + extern char *_rl_get_keyname (int key); + extern char *_rl_untranslate_macro_value (char *seq, int use_escapes); + + for (key = 0; key < KEYMAP_SIZE; key++) +{ + switch (map[key].type) + { + case ISMACR: + break; + case ISFUNC: + if (map[key].function != bash_execute_unix_command || xmap[key].type != ISMACR) + continue; + + keyname = _rl_get_keyname (key); + out = _rl_untranslate_macro_value ((char *)xmap[key].function, 0); + fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "", + keyname, + out ? out : ""); + xfree (keyname); + xfree (out); + break; + case ISKMAP: + if (xmap[key].type != ISKMAP) + continue; + + prefix_len = prefix ? strlen (prefix) : 0; + if (key == ESC) + { + keyname = (char *)xmalloc (3 + prefix_len); + if (prefix) + strcpy (keyname, prefix); + keyname[prefix_len] = '\\'; + keyname[prefix_len + 1] = 'e'; + keyname[prefix_len + 2] = '\0'; + } + else + { + keyname = _rl_get_keyname (key); + if (prefix) + { + out = (char *)xmalloc (strlen (keyname) + prefix_len + 1); + strcpy (out, prefix); + strcpy (out + prefix_len, keyname); + xfree (keyname); + keyname = out; + } + } + + _print_unix_command_map_internal (FUNCTION_TO_KEYMAP (map, key), FUNCTION_TO_KEYMAP (xmap, key), keyname); + xfree (keyname); + break; + } +} +} + int print_unix_command_map () { - Keymap save, cmd_xmap; + Keymap kmap, cmd_xmap; - save = rl_get_keymap (); - cmd_xmap = get_cmd_xmap_from_keymap (save); - rl_set_keymap (cmd_xmap); - rl_macro_dumper (1); - rl_set_keymap (save); + kmap = rl_get_keymap (); + cmd_xmap = get_cmd_xmap_from_keymap (kmap); + _print_unix_command_map_internal (kmap, cmd_xmap, (char *)NULL); return 0; } diff --git a/lib/readline/bind.c b/lib/readline/bind.c index b6970df6..87b0a31a 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -2483,7 +2483,7 @@ rl_list_funmap_names (void) xfree (funmap_names); } -static char * +char * _rl_get_keyname (int key) { char *keyname; -- 2.21.0
parser perversities (was Re: make install failed; dump core in mkdir)
On 2019/12/02 07:04, pepa65 wrote: it would be nice to be able to omit 'do'. like: set -- 1 2 3 for i { echo $i } 1 2 3 or: for i;{ echo $i;} 1 2 3
Two states of empty arryays
Hello, Depending on how an empty array is declared, it is not stored with the same state. # Empty array declared without parenthesis unset myArr declare -a myArr typeset -p myArr echo "${#myArr[@]}" output: declare -a myArr 0 # Empty array declared without parenthesis unset myArr declare -a myArr=() typeset -p myArr echo "${#myArr[@]}" output: declare -a myArr=() 0 What is the reason for having different states for empty arrays? -- Lea Gris
Two states of empty arrays
Hello, Depending on how an empty array is declared, it is not stored with the same state. # Empty array declared without parenthesis unset myArr declare -a myArr typeset -p myArr echo "${#myArr[@]}" output: declare -a myArr 0 # Empty array declared without parenthesis unset myArr declare -a myArr=() typeset -p myArr echo "${#myArr[@]}" output: declare -a myArr=() 0 What is the reason for having different states for empty arrays? -- Lea Gris -- Léa Gris signature.asc Description: OpenPGP digital signature
Re: Two states of empty arrays
On Thu, Dec 12, 2019 at 1:10 PM Léa Gris wrote: > Hello, > > Depending on how an empty array is declared, it is not stored with the > same state. > > # Empty array declared without parenthesis > unset myArr > declare -a myArr > typeset -p myArr > echo "${#myArr[@]}" > > output: > declare -a myArr > 0 > Here, you haven't yet defined a parameter named myArr; you have only set the array attribute on the name myArr. You can see something similar with other attributes: $ declare -i x $ [[ -v x ]] || echo "x not defined" x not defined $ declare -p x declare -i x > > # Empty array declared without parenthesis > unset myArr > declare -a myArr=() > typeset -p myArr > echo "${#myArr[@]}" > > output: > declare -a myArr=() > 0 > > With the assignment, you have an actual parameter named myArr. Continuing the integer attribute example from above, $ x=3 $ declare -p x declare -i x="3" $ [[ -v x ]] || echo "x not defined" # No output -- Clint
Re: Two states of empty arrays
On 12/12/19 12:08 PM, Léa Gris wrote: Hello, Depending on how an empty array is declared, it is not stored with the same state. # Empty array declared without parenthesis unset myArr declare -a myArr typeset -p myArr echo "${#myArr[@]}" This is an unset variable with the array attribute; you have not assigned a value. # Empty array declared without parenthesis unset myArr declare -a myArr=() This is an empty array variable; you have assigned a value. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Not missing, but very hard to see (was Re: Backslash missing in brace expansion)
On 2019/12/06 14:14, Chet Ramey wrote: Seems very hard to print out that backquote though. Closest I got was bash converting it to "''": read -r -a a< <(printf "%q " {Z..a}) my -p a declare -a a=([0]="Z" [1]="\\[" [2]="''" [3]="\\]" [4]="\\^" [5]="_" [6]="\\\`" [7]="a") #2 is where backslash would be and has been transliterated to the pair of single quotes. Guess "" was too messy looking?
Re: Not missing, but very hard to see (was Re: Backslash missing in brace expansion)
On Thu, Dec 12, 2019 at 11:43:58AM -0800, L A Walsh wrote: > > read -r -a a< <(printf "%q " {Z..a}) > > my -p a > declare -a a=([0]="Z" [1]="\\[" [2]="''" [3]="\\]" [4]="\\^" [5]="_" > [6]="\\\`" [7]="a") Nice try. I guess the takeaway from this thread is: "You cannot mix capital and lowercase letters in brace expansion. If you try, you get garbage out."
Re: Binding Containing Escape Key Fails to Escape History Search
On 12/8/19 7:15 PM, sunnycemet...@gmail.com wrote: On 2019-11-04 14:41, Chet Ramey wrote: If \ef and Alt+f generate distinct character sequences, you can bind them separately. If they don't, you can't. This has nothing to do with whether or not incremental searching expands keyboard macros. In that case, how would one go about binding æ such that it both exits an incremental search and executes forward-word? There isn't, really. Any character that doesn't end the search or map to one of a few editing functions that the isearch code uses to modify the search string is added to the search string. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: Not missing, but very hard to see (was Re: Backslash missing in brace expansion)
On 12.12. 21:43, L A Walsh wrote: On 2019/12/06 14:14, Chet Ramey wrote: Seems very hard to print out that backquote though. Closest I got was bash converting it to "''": The backquote is in [6], and the backslash disappears, you just get the pair of quotes in [2] because that's how printf %q outputs an empty string. read -r -a a< <(printf "%q " {Z..a}) my -p a declare -a a=([0]="Z" [1]="\\[" [2]="''" [3]="\\]" [4]="\\^" [5]="_" [6]="\\\`" [7]="a") -- Ilkka Virta / itvi...@iki.fi
Re: Two states of empty arrays
Le 12/12/2019 à 20:13, Chet Ramey écrivait : >> # Empty array declared without parenthesis >> unset myArr >> declare -a myArr >> typeset -p myArr >> echo "${#myArr[@]}" > > This is an unset variable with the array attribute; you have not assigned a > value. >> # Empty array declared without parenthesis >> unset myArr >> declare -a myArr=() > > This is an empty array variable; you have assigned a value. Thank you and Clint, it makes sense now. I was trying to play the the -v test to detect when an array or associative array has been declared, not necessarily assigned entries key, values, to not error when Bash runs with -o nounset Like here: #!/usr/bin/bash set -o nounset myArr+=(["key"]="value") ERR: line 3: key: unbound variable I can test the type of myArr this way: if [[ "$(typeset -p myArr 2>&1)" =~ ^declare\ -A ]]; then myArr+=(["key"]="value") fi But it looks sub-optimal to test the type and declaration of a variable. The -v test flag cannot be used because it requires the associative array to contain at least a [key]=value entry as mentioned in the man bash.1: >-v varname > True if the shell variable varname is set (has been assigned a > value). _has been assigned a value_ -- Lea Gris
Re: Two states of empty arrays
Hello Léa! Léa Gris wrote: > I was trying to play the the -v test to detect when an array or > associative array has been declared, not necessarily assigned entries > key, values, to not error when Bash runs with -o nounset Just for the curious: What is your attention here? I think that most useful questions (Is there an element in the array? Is there a value for a given key?) can be answered in a simpler way: #!/bin/bash set -o nounset # From what I learned today it seems to be good practice to always # assign and empty array to when declaring an associative array: declare -A assoc=() echo ${#assoc[@]} # Are there elements in it? assoc[key1]=val1 assoc[key2]= for key in key1 key2 key3; do if [[ -n ${assoc[$key]+isset} ]]; then echo "Element for $key is set" else echo "No Element for $key" fi done Best regards, Martin
Re: Not missing, but very hard to see (was Re: Backslash missing in brace expansion)
On 2019/12/12 13:01, Ilkka Virta wrote: On 12.12. 21:43, L A Walsh wrote: On 2019/12/06 14:14, Chet Ramey wrote: Seems very hard to print out that backquote though. Closest I got was bash converting it to "''": The backquote is in [6], and the backslash disappears, you just get the pair of quotes in [2] because that's how printf %q outputs an empty string. - I'm sorry, but you are mistaken. The characters from 'Z' (0x5A) through 'z' (0x61) are: 0x5A 0x5B 0x5C 0x5D 0x5E 0x5F 0x60 0x61 Z[\] ^ _ `a the backslash comes between the two square brackets. Position [6] is the "Grave Accent" (or backquote). It is quoted properly. As for %q printing an empty string for 0x5C "%q" causes printf to output the corresponding argument in a format that can be reused as shell input. For that string to be empty would mean there is no character at hex value 0x5C (unicode U+005C), which isn't so. read -r -a a< <(printf "%q " {Z..a}) my -p a declare -a a=([0]="Z" [1]="\\[" [2]="''" [3]="\\]" [4]="\\^" [5]="_" [6]="\\\`" [7]="a")
Re: Not missing, but very hard to see (was Re: Backslash missing in brace expansion)
On 12/12/19 9:57 PM, L A Walsh wrote: > > > On 2019/12/12 13:01, Ilkka Virta wrote: >> On 12.12. 21:43, L A Walsh wrote: >> >>> On 2019/12/06 14:14, Chet Ramey wrote: >>> >>> Seems very hard to print out that backquote though. Closest I got >>> was bash converting it to "''": >>> >> >> The backquote is in [6], and the backslash disappears, you just get >> the pair of quotes in [2] because that's how printf %q outputs an >> empty string. >> > - > > I'm sorry, but you are mistaken. How so? > The characters from 'Z' (0x5A) through 'z' (0x61) are: > > 0x5A 0x5B 0x5C 0x5D 0x5E 0x5F 0x60 0x61 > Z [ \ ] ^ _ ` a > > the backslash comes between the two square brackets. > > Position [6] is the "Grave Accent" (or backquote). > > It is quoted properly. But... that's exactly what was said. > As for %q printing an empty string for 0x5C > > "%q" causes printf to output the corresponding argument in a > format that can be reused as shell input. > > For that string to be empty would mean there is no character at hex > value 0x5C (unicode U+005C), which isn't so. But there isn't. An empty string was passed as an argument to printf, because the backslash was *converted* via escaping, into an empty string, *before* it was passed on the command line as an argv element to the printf builtin. Do you think that because printf is a builtin, and you didn't use /bin/printf, that somehow means it is exempt from the usual rule of how shells work, and gets to see its own argv before the parser reinterprets it? >> read -r -a a< <(printf "%q " {Z..a}) my -p a >>> declare -a a=([0]="Z" [1]="\\[" [2]="''" [3]="\\]" [4]="\\^" [5]="_" >>> [6]="\\\`" [7]="a") >>> >> >> >> -- Eli Schwartz Bug Wrangler and Trusted User signature.asc Description: OpenPGP digital signature