diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-10-29 12:49:21 +0000 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-10-29 12:49:21 +0000 |
commit | bad5c7d5a50e7f340d3a5daff59d7f3c18c0ab8f (patch) | |
tree | 9fecd1c7daf53c89ab9532308a39cc8b4abbb568 /fish | |
parent | 9de4dfddc7acf0d6c9d3a32f5d923ffa650cbce1 (diff) | |
download | libguestfs-bad5c7d5a50e7f340d3a5daff59d7f3c18c0ab8f.tar.gz libguestfs-bad5c7d5a50e7f340d3a5daff59d7f3c18c0ab8f.tar.xz libguestfs-bad5c7d5a50e7f340d3a5daff59d7f3c18c0ab8f.zip |
fish: Add GUESTFISH_PS1 environment variable to control prompt.
Diffstat (limited to 'fish')
-rw-r--r-- | fish/fish.c | 143 | ||||
-rw-r--r-- | fish/guestfish.pod | 69 |
2 files changed, 203 insertions, 9 deletions
diff --git a/fish/fish.c b/fish/fish.c index c46cd116..332ef1ac 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -69,6 +69,7 @@ static void error_cb (guestfs_h *g, void *data, const char *msg); static void initialize_readline (void); static void cleanup_readline (void); #ifdef HAVE_LIBREADLINE +static char *decode_ps1 (const char *); static void add_history_line (const char *); #endif @@ -614,12 +615,14 @@ shell_script (void) #define FISH "><fs> " +static char *ps1 = NULL; static char *line_read = NULL; static char * rl_gets (int prompt) { #ifdef HAVE_LIBREADLINE + char *p = NULL; if (prompt) { if (line_read) { @@ -627,7 +630,9 @@ rl_gets (int prompt) line_read = NULL; } - line_read = readline (prompt ? FISH : ""); + p = prompt && ps1 ? decode_ps1 (ps1) : NULL; + line_read = readline (prompt ? (ps1 ? p : FISH) : ""); + free (p); if (line_read && *line_read) add_history_line (line_read); @@ -1431,14 +1436,7 @@ static void initialize_readline (void) { #ifdef HAVE_LIBREADLINE - const char *home; - - home = getenv ("HOME"); - if (home) { - snprintf (histfile, sizeof histfile, "%s/.guestfish", home); - using_history (); - (void) read_history (histfile); - } + const char *str; rl_readline_name = "guestfish"; rl_attempted_completion_function = do_completion; @@ -1449,6 +1447,25 @@ initialize_readline (void) * they wish. */ (void) rl_variable_bind ("completion-ignore-case", "on"); + + /* Set up the history file. */ + str = getenv ("HOME"); + if (str) { + snprintf (histfile, sizeof histfile, "%s/.guestfish", str); + using_history (); + (void) read_history (histfile); + } + + /* Set up the prompt. */ + str = getenv ("GUESTFISH_PS1"); + if (str) { + free (ps1); + ps1 = strdup (str); + if (!ps1) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + } #endif } @@ -1483,6 +1500,114 @@ add_history_line (const char *line) add_history (line); nr_history_lines++; } + +static int decode_ps1_octal (const char *s, size_t *i); +static int decode_ps1_hex (const char *s, size_t *i); + +/* Decode 'str' into the final printable prompt string. */ +static char * +decode_ps1 (const char *str) +{ + char *ret; + size_t len = strlen (str); + size_t i, j; + + /* Result string is always smaller than the input string. This will + * change if we add new features like date/time substitution in + * future. + */ + ret = malloc (len + 1); + if (!ret) { + perror ("malloc"); + exit (EXIT_FAILURE); + } + + for (i = j = 0; i < len; ++i) { + if (str[i] == '\\') { /* Start of an escape sequence. */ + if (i < len-1) + i++; + switch (str[i]) { + case '\\': + ret[j++] = '\\'; + break; + case '[': + ret[j++] = RL_PROMPT_START_IGNORE; + break; + case ']': + ret[j++] = RL_PROMPT_END_IGNORE; + break; + case 'a': + ret[j++] = '\a'; + break; + case 'e': + ret[j++] = '\033'; + break; + case 'n': + ret[j++] = '\n'; + break; + case 'r': + ret[j++] = '\r'; + break; + case '0'...'7': + ret[j++] = decode_ps1_octal (str, &i); + i--; + break; + case 'x': + i++; + ret[j++] = decode_ps1_hex (str, &i); + i--; + break; + default: + ret[j++] = '?'; + } + } + else + ret[j++] = str[i]; + } + + ret[j] = '\0'; + return ret; /* caller frees */ +} + +static int +decode_ps1_octal (const char *s, size_t *i) +{ + size_t lim = 3; + int ret = 0; + + while (lim > 0 && s[*i] >= '0' && s[*i] <= '7') { + ret *= 8; + ret += s[*i] - '0'; + (*i)++; + lim--; + } + + return ret; +} + +static int +decode_ps1_hex (const char *s, size_t *i) +{ + size_t lim = 2; + int ret = 0; + + while (lim > 0 && c_isxdigit (s[*i])) { + ret *= 16; + if (s[*i] >= '0' && s[*i] <= '9') + ret += s[*i] - '0'; + else if (s[*i] >= 'a' && s[*i] <= 'f') + ret += s[*i] - 'a' + 10; + else if (s[*i] >= 'A' && s[*i] <= 'F') + ret += s[*i] - 'A' + 10; + (*i)++; + lim--; + } + + if (lim == 2) /* \x not followed by any hex digits */ + return '?'; + + return ret; +} #endif int diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 4a665e0f..94b3df48 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -1103,6 +1103,71 @@ interactively. You can enable them even for non-interactive modes using I<--progress-bars>, and you can disable them completely using I<--no-progress-bars>. +=head1 PROMPT + +You can change or add colours to the default prompt +(C<E<gt>E<lt>fsE<gt>>) by setting the C<GUESTFISH_PS1> environment +variable. A simple change can be made simply by setting this to an +alternate string: + + $ GUESTFISH_PS1='(type a command) ' + $ export GUESTFISH_PS1 + $ guestfish + [...] + (type a command) ls + +You can also use special escape sequences, as described in the table +below: + +=over 4 + +=item \\ + +A literal backslash character. + +=item \[ + +=item \] + +Place non-printing characters (eg. terminal control codes for colours) +between C<\[...\]>. What this does it to tell the L<readline(3)> +library that it should treat this subsequence as zero-width, so that +command-line redisplay, editing etc works. + +=item \a + +A bell character. + +=item \e + +An ASCII ESC (escape) character. + +=item \n + +A newline. + +=item \r + +A carriage return. + +=item \NNN + +The ASCII character whose code is the octal value NNN. + +=item \xNN + +The ASCII character whose code is the hex value NN. + +=back + +=head2 EXAMPLES OF PROMPTS + +Note these these require a terminal that supports ANSI escape codes. + + GUESTFISH_PS1='\[\e[1;30m\]><fs>\[\e[0;30m\] ' + +A bold black version of the ordinary prompt. + =head1 GUESTFISH COMMANDS The commands in this section are guestfish convenience commands, in @@ -1162,6 +1227,10 @@ Used with the I<--remote> option to specify the remote guestfish process to control. See section L</REMOTE CONTROL GUESTFISH OVER A SOCKET>. +=item GUESTFISH_PS1 + +Set the command prompt. See L</PROMPT>. + =item HEXEDITOR The L</hexedit> command uses C<$HEXEDITOR> as the external hex |