home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: gnu.bash.bug
- Path: sparky!uunet!cis.ohio-state.edu!arissoft.COM!john
- From: john@arissoft.COM
- Subject: "Philosophical" bug: Bash needs an "invisiblity" sequence inside PS1
- Message-ID: <9209060053.AA02428@arissoft.com>
- Sender: gnulists@ai.mit.edu
- Organization: GNUs Not Usenet
- Distribution: gnu
- Date: Sun, 6 Sep 1992 00:53:13 GMT
- Approved: bug-bash@prep.ai.mit.edu
- Lines: 286
-
- I use GNU Bash, version 1.12.9, and the terminal program I use is Stuart
- 2.4 on a NeXT, which has title-bar-setting escape sequences that are a
- superset of those understood by Xterm. A problem I was experiencing was
- that the Readline library used by Bash doesn't know what part of the prompt
- is actually visible. So, if I have a big, nasty PS1 variable that puts
- lots of things in the title bar, Readline decides I've hit the 80th column
- and breaks the line way too early. (About the 15th character, with my
- current PS1 setting.) Things just get worse when you start doing cursor
- motion commands, redraws, etc.
-
- Very bad.
-
- I thought of a reasonably simple fix. Introduce two new sequences into
- the PS[124] variables: "\i" to say that the following characters are
- invisible and shouldn't get put into the prompt that Readline knows
- about, and (naturally) "\I" to turn off invisibility for the following
- characters. Now, a PS1 sequence to set the titlebar for an Xterm (or
- a Stuart, in my case) might be
-
- PS1="\i^[]0;\u@\h:\w^G\I% '
-
- I had originally planned just to send in a whiney message complaining
- about this and sit around and wait until somebody did something, but
- I figured I'd like this feature right away, and besides, you probably
- wouldn't stick this feature in future versions anyway ... :-) So, a
- little diddling around produced the following apparently-operational
- diff.
-
- The code works like this: it introduces a global variable called
- invisible_readline_prompt that is effectively a second return value
- from decode_prompt_string(). When prompt_again() calls
- decode_prompt_string(), it prints invisible_readline_prompt to stderr.
-
- decode_prompt_string() was modified to have two states. One state is
- the "invisible" state, and the other is the "visible" state. In the
- visible state, operation is as it was before. The string result is
- built up a little bit at a time. However, the sequences \i and \I
- switch to/from the invisible state, and in the invisible state, the
- little chunks get added to a new local variable called invisible_result
- (use of invisible_result was a cut 'n' paste from the code that dealt
- with result). When the function is done, it copies invisible_result
- out to invisible_readline_prompt.
-
- I wouldn't say this was the greatest implementation in the world, but
- it was quick and easy, and I think the \i and \I are easy to use. (And
- probably won't break existing code.) Feel free (of course) to throw
- this code out and do it like it should have been done. But please --
- put SOMETHING like this in the next Bash. The problem with invisible
- prompt characters messing up the line breaking was terribly annoying.
-
- Incidentally, to Brian Fox and whoever else has contributed code to
- Bash: I'm extremely impressed with Bash, both from a user standpoint
- and from a standpoint of a guy who just had to hack it to add a
- little feature. The code is extremely readable and maintainable.
- Good work.
-
- --
- john@arissoft.com (John Dawson)
-
- Enclosure:
- --------------------------------------------------------------------
- *** parse.y.old Sat Sep 5 16:20:42 1992
- --- parse.y Sat Sep 5 19:18:29 1992
- ***************
- *** 601,606 ****
- --- 601,607 ----
-
-
- #if defined (READLINE)
- char *current_readline_prompt = (char *)NULL;
- + char *invisible_readline_prompt = (char *)NULL;
- char *current_readline_line = (char *)NULL;
- int current_readline_line_index = 0;
-
-
- ***************
- *** 2328,2334 ****
- ps2_prompt = get_string_value ("PS2");
-
-
- if (!prompt_string_pointer)
- ! prompt_string_pointer = &ps1_prompt;
-
-
- if (*prompt_string_pointer)
- temp_prompt = decode_prompt_string (*prompt_string_pointer);
- --- 2329,2337 ----
- ps2_prompt = get_string_value ("PS2");
-
-
- if (!prompt_string_pointer)
- ! {
- ! prompt_string_pointer = &ps1_prompt;
- ! }
-
-
- if (*prompt_string_pointer)
- temp_prompt = decode_prompt_string (*prompt_string_pointer);
- ***************
- *** 2335,2340 ****
- --- 2338,2349 ----
- else
- temp_prompt = savestring ("");
-
-
- + if (invisible_readline_prompt)
- + {
- + fprintf(stderr, "%s", invisible_readline_prompt);
- + fflush(stderr);
- + }
- +
-
- current_prompt_string = *prompt_string_pointer;
- prompt_string_pointer = &ps2_prompt;
-
-
- ***************
- *** 2356,2361 ****
- --- 2365,2371 ----
- }
- free (temp_prompt);
- }
- +
-
- }
-
-
- #include "maxpath.h"
- ***************
- *** 2376,2381 ****
- --- 2386,2393 ----
- \$ a $ or a # if you are root
- \<octal> character code in octal
- \\ a backslash
- + \i mark beginning of invisible sequence
- + \I mark end of invisible sequence
- */
- #include <sys/param.h>
- #include <time.h>
- ***************
- *** 2388,2397 ****
- --- 2400,2414 ----
- int result_size = PROMPT_GROWTH;
- int result_index = 0;
- char *result = (char *)xmalloc (PROMPT_GROWTH);
- + int invisible_result_size = PROMPT_GROWTH;
- + int invisible_result_index = 0;
- + char *invisible_result = (char *)xmalloc (PROMPT_GROWTH);
- int c;
- char *temp = (char *)NULL;
- + int invisible = 0;
-
-
- result[0] = 0;
- + invisible_result[0] = 0;
- while (c = *string++)
- {
- if (c == '\\')
- ***************
- *** 2545,2573 ****
- case '\\':
- temp = savestring ("\\");
- goto add_string;
-
-
- default:
- temp = savestring ("\\ ");
- temp[1] = c;
-
-
- add_string:
- ! if (c)
- ! string++;
- ! result =
- ! (char *)sub_append_string (temp, result,
- ! &result_index, &result_size);
- ! temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
- ! result[result_index] = '\0';
- ! break;
- }
- }
- else
- {
- ! while (3 + result_index > result_size)
- ! result = (char *)xrealloc (result, result_size += PROMPT_GROWTH);
-
-
- ! result[result_index++] = c;
- ! result[result_index] = '\0';
- }
- }
-
-
- --- 2562,2628 ----
- case '\\':
- temp = savestring ("\\");
- goto add_string;
- +
-
- + case 'i':
- + invisible = 1;
- + temp = savestring ("");
- + goto add_string;
-
-
- + case 'I':
- + invisible = 0;
- + temp = savestring ("");
- + goto add_string;
- +
-
- default:
- temp = savestring ("\\ ");
- temp[1] = c;
-
-
- add_string:
- ! if (invisible)
-
- ! {
- ! if (c)
- ! string++;
- ! invisible_result =
- ! (char *)sub_append_string (temp, invisible_result,
- ! &invisible_result_index,
- ! &invisible_result_size);
- ! temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
- ! invisible_result[invisible_result_index] = '\0';
- ! break;
- ! }
- ! else
- ! {
- ! if (c)
- ! string++;
- ! result =
- ! (char *)sub_append_string (temp, result,
- ! &result_index, &result_size);
- ! temp = (char *)NULL; /* Free ()'ed in sub_append_string (). */
- ! result[result_index] = '\0';
- ! break;
- ! }
- }
- }
- else
- {
- ! if (invisible)
- ! {
- ! while (3 + invisible_result_index > invisible_result_size)
- ! result = (char *)
- ! xrealloc(invisible_result,
- ! invisible_result_size += PROMPT_GROWTH);
-
-
- ! invisible_result[invisible_result_index++] = c;
- ! invisible_result[invisible_result_index] = '\0';
- ! }
- ! else
- ! {
- ! while (3 + result_index > result_size)
- ! result = (char *)xrealloc (result, result_size+=PROMPT_GROWTH);
- !
-
- ! result[result_index++] = c;
- ! result[result_index] = '\0';
- ! }
- }
- }
-
-
- ***************
- *** 2582,2587 ****
- --- 2637,2646 ----
- result = string_list (list);
- dispose_words (list);
- }
- +
-
- + if (invisible_readline_prompt)
- + free(invisible_readline_prompt);
- + invisible_readline_prompt = invisible_result;
-
-
- return (result);
- }
- --------------------------------------------------------------------
-
-