Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make title bar work out-of-the-box with Gnome Terminal #609

Closed
ottok opened this issue Jun 25, 2020 · 16 comments · Fixed by #665
Closed

Make title bar work out-of-the-box with Gnome Terminal #609

ottok opened this issue Jun 25, 2020 · 16 comments · Fixed by #665
Labels
enhancement Feature request title Related to setting the terminal title
Milestone

Comments

@ottok
Copy link
Contributor

ottok commented Jun 25, 2020

Shell: bash
Operating system: Ubuntu 20.04
Liquid Prompt version (tag, commit): 1.11 Debian revision 3 (includes customized settings, see https://sources.debian.org/src/liquidprompt/1.11-3/debian/patches/debian-default-cfg.patch/)

I recently learned about liquidprompt on the Debian developer mailing list and I love it after using for some weeks now.

The only problem seems to be that the Gnome Terminal window title is not set by default:
image

I can enable it manually with LP_ENABLE_TITLE=1 but it does not feel as usable as the rest of liquidprompt since the title bar has excess info that is not relevant for a title bar:
image

In the title bar it would be enough to show what Bash shows by default (mainly user, host and path). Having time or temperature or git branch etc in the title bar does not feel very useful.

Could liquidprompt be made so that it does not override the title with nothing and instead keeps the default bash title there?

If feel that would be the optimal solution from an usability point of view.

This is partially a duplicate of #78 but I thought a new issue would be in place for discussing further development of the title bar feature.

Thanks for a great piece of software!

@ottok
Copy link
Contributor Author

ottok commented Jun 25, 2020

My personal workaround for this was to add in .bashrc the line PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'

image

@Rycieos
Copy link
Collaborator

Rycieos commented Jun 25, 2020

keep the default bash title there

I'm not sure that there is a "default bash title". Bash by default doesn't interact with a terminal or terminal emulator much, if at all. For it to do so, you need to print out ANSI escape codes to tell the terminal to do something. My guess is that there is some system PS1 or similar in /etc/bashrc or similar on your system that sets a nice default for a terminal title. I'd be happy to be proven wrong though.

What you see right now ("Terminal") is what happens when no terminal is set, which is the default for Gnome terminal. For Mintty, the default title is the launched command (-bash in my case).

Your workaround obviously works fine, but for Liquidprompt v1, the recommended way to set the title would be to write your own .ps1 file, replacing line 48 with the parts you want to show up (in your case,

LP_TITLE="$(_lp_title "${LP_BRACKET_OPEN}${LP_USER}${LP_HOST}${LP_PERM}${LP_PWD}${LP_BRACKET_CLOSE})"

I would agree with your statement that the default Liquidprompt title as it stands right now isn't very useful. I'd like to see a default that doesn't copy PS1 so closely.

This is as good as any issue to discuss my plans with the title:

  1. Keep it easy for users to customize it, using the same drop in pieces as PS1.
  2. Have two versions; one while waiting on the prompt for user input, and one while a command is running, so that:
  3. By default, the second version is the command that is currently being run, maybe with a prefix of the current directory? I'm imagining like so: [mark:~/workdir] $ sleep 100.

And I'm glad to hear people are still recommending this project! With the 4 year long development hiatus, I know some people have lost interest, but I'm hoping to put some real work in and get this project back on track.

@Rycieos Rycieos added enhancement Feature request title Related to setting the terminal title labels Jun 25, 2020
@Rycieos Rycieos added this to the v2.0 milestone Jun 25, 2020
@ottok
Copy link
Contributor Author

ottok commented Jun 25, 2020

I'm not sure that there is a "default bash title". Bash by default doesn't interact with a terminal or terminal emulator much, if at all.

Right. I meant the default out-of-the-box experience as Bash is delivered in Debian with accompanying default system .bashrc files, which has:

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;

Showing time, load, git status etc is naturally unnecessary for the title. I am fine with just the host and path, which in my day-to-day use is enough, but I also like the idea of showing the current command. That way I can see on a glimpse what is the status of that window.

There are a couple of build and test systems that populate the window title with a progress indicator (timer or 0-100% number) when the command inside them is running, and thus you get a glimpse of the status without having to read the contents of the window. That is however not a feature that can be implemented in a generic way for everybody in LP.

Just for illustration, this is how it looks like in Gnome when multiple terminals are open:
image

The title is visible in the window title, on hover also under the window, and if there are tabs, in each tab title.

@ottok
Copy link
Contributor Author

ottok commented Jul 4, 2020

Now after some thought, I think the title bar by default should be as short as possible to avoid clutter, and in general to start with the most significant information (instead of just username and host).

image

The most significant information from a prompt is:

  1. What command is currently running
  2. If nothing is running, what path is open

The username and hostname are interesting mostly only if I am connected to a remote host, but in those cases the remote host bash prompt overrides the window title with it's own signal anyway, so my local Liquid Prompt settings don't matter much in those cases.

@Rycieos
Copy link
Collaborator

Rycieos commented Dec 9, 2020

I meant the default out-of-the-box experience as Bash is delivered in Debian with accompanying default system .bashrc files

If you have LP_ENABLE_TITLE=0, Liquidprompt will not override any title you have previously. The reason it overrides that system "title" is because your system saves it as part of the PS1, which Liquidprompt obviously needs to override. If that file had stored the title printing in PROMPT_COMMAND instead, Liquidprompt would have saved that and still ran it.

But thanks to you I have improved the title capabilities in v2.0.0-beta.1. You have two options (if you don't like the default title):

  1. Make your own theme that calls either _lp_formatted_title() or _lp_raw_title() to set your custom title.
  2. Call lp_title() once to set your own title. Maybe something like:
lp_title '\H:\w'

NOTE: This will no longer work: prompt escape sequences like \w will no longer work in Liquidprompt titles.

I also like the idea of showing the current command

Me too! I'm hoping to add such a feature before v2.0.0 final.

@ottok
Copy link
Contributor Author

ottok commented Dec 9, 2020 via email

@Rycieos
Copy link
Collaborator

Rycieos commented Dec 28, 2020

Here is my design:

  • Add LP_ENABLE_TITLE_COMMAND, default enabled (since title is default disabled).
  • Display the currently running command after the "real title".
  • When waiting on a prompt for user input, display no command.

It would look like this:

[user@server:~] $ 

then with a command:

[user@server:~] $ sleep 20

Here is the problem: there is no way to postpend to the current terminal title. To set a title, you must set the whole thing. And to set a title, you must print it to the terminal screen (where the terminal sees the escape sequence and captures it without the user seeing it).

The second problem is that if you want to include time, username, hostname, working directory, or current prompt mark in the title, they must be first processed by the shell. The example title above is not printed directly, it would instead look like this:

[\u@\h:\w] \$

or in Zsh

[%n@%m:%~] %(!.#.%%)

This sequence is interpreted by the shell when it reads PS1 and prints it to the screen. Which works great, saving us some work looking those data points up. But, to add the running command to the title, we need to print it after PS1 has already been evaluated. Which means if we simply print the title to the screen, it would look like the above instead of real username, etc.

Other things that don't work:

  • Use the prompt expansion mode: ${PS1@P}. This needs Bash 4.4+.
  • Use print -P or ${(%%)PS1}. This only works on Zsh.
  • Trick the prompt into printing PS3. PS3 expansion does not evaluate the escape sequences (all the others do).
  • Hacks involving running another copy of the shell to make it evaluate the prompt. Forking is too slow.

So there is no easy solution, but I have a possible solution: remove all prompt escape sequences. Some pros and cons:

Pros:

  • All data functions would actually return data instead of non-data escape codes. This would make it clearer, and allow for comparison to the data.
  • Titles would be much easier, and would not need to be embedded in the PS1
  • As noted in Ksh compatibility #608 (comment), prompt escape codes is the one major limiting factor preventing Liquidprompt from supporting Ksh.

Cons:

  • More work to build and test data functions that return these "new" datum.
  • Slightly slower to generate the data, though some like user and hostname are done only once on startup.
  • Switching to another user won't show changes in the prompt unless that user loads Liquidprompt. Though this already does not work very well at all, so not much would be lost.

Spitballing, any thoughts?

@ottok
Copy link
Contributor Author

ottok commented Dec 30, 2020 via email

@Rycieos
Copy link
Collaborator

Rycieos commented Jan 26, 2021

I'm moving this to v2.1, since v2.0 is getting large and long already, and this mostly depends on #651, which really should wait until after v2.0.

@Rycieos Rycieos modified the milestones: v2.0, v2.1 Jan 26, 2021
Rycieos added a commit that referenced this issue Mar 3, 2021
This feature depends on the removal of the prompt escape sequences that
came before. Part of that is the removal of adding the title to $PS1:
now it is just print to the screen. This could improve speed slightly,
as the shell doesn't need to parse that text. But it does prevent usage
of prompt escape codes in the title.

I also needed to rework how the runtime feature was handled, since it
monopolized the DEBUG trap in Bash. Now it can handle multiple features
that need to run after the user has submitted the command, but before it
runs.

The feature itself is simple: lookup the latest command in the history,
and print the normal title postpended by that command to the screen,
formatted as a terminal title. Note that Bash's $BASH_COMMAND is not
great, as it only contains the current _command_, not the whole command
line.

Resolves #609
@Rycieos
Copy link
Collaborator

Rycieos commented Mar 3, 2021

I have pushed a commit (1044321) on branch title-command that adds a feature to display the currently running command as part of the terminal title. It works pretty much exactly like how I described above.

I would appreciate it if you could test it and let me know what you think.

@augmentedfourth
Copy link
Contributor

It works in macOS, though I can't figure out why. sleep 3 causes sleep to show up in the title, but not until about a half-second after it starts (and it goes back to -bash right as sleep finishes). And after I quit vim, the "Thanks for flying Vim" title stays up there seemingly permanently, even if I run something like sleep 20.

I don't understand the __lp_print_title_command function, as the bash string variable parsing on $command doesn't seem to work for me in an interactive session. I also don't know how you discover the running binary when it's part of a script and wasn't actually entered in the shell history.

@augmentedfourth
Copy link
Contributor

Never mind. It looks like it works exactly the same in my macOS bash shell as in the current master. So I really don't know what's happening at all.

@Rycieos
Copy link
Collaborator

Rycieos commented Mar 4, 2021

I don't understand the __lp_print_title_command function, as the bash string variable parsing on $command doesn't seem to work for me in an interactive session. I also don't know how you discover the running binary when it's part of a script and wasn't actually entered in the shell history.

That part was inspired by bash-preexec: https://github.com/rcaloras/bash-preexec/blob/10b41c5ed8dc28fe5bb6970cb8e12e618aa5a998/bash-preexec.sh#L230

It is actually entered into the shell history instantly, that's why running history shows itself as the most recent command.

I checked Bash 3.2 - 5.1 and the format stayed the same. Does HISTTIMEFORMAT= builtin history 1 not print 1000 HISTTIMEFORMAT= builtin history 1 for you?

@augmentedfourth
Copy link
Contributor

Yeah, command is set properly, but the substring extraction doesn't work and the number stays on the beginning. command=${command#* } works better than the current line 2562. But is the goal to turn the title to have the whole command or just the binary that's currently executing?

@Rycieos
Copy link
Collaborator

Rycieos commented Mar 5, 2021

command=${command#* } works better than the current line 2562.

Shoot, so that means there can be no spaces at the beginning. Makes sense, but also makes it much harder to do with parameter substitution and not regex. I can't use regex without calling another process, which would slow this down. I'll try to figure something out.

But is the goal to turn the title to have the whole command or just the binary that's currently executing?

Yes, the whole command line. This is the only thing I could get working in Zsh, so this way it is consistent. I could use $BASH_COMMAND instead, which would:

  • for sleep 4; sleep 2: would first show sleep 4, then sleep 2, when each is executing, and
  • for sleep 4 | sleep 2: would show only sleep 2 for the 4 seconds.

The first point is fine, and some might prefer it, but the second point is probably never what anyone wants. To show the whole command line instead is just a safer and more consistent with Zsh approach.

@Rycieos
Copy link
Collaborator

Rycieos commented Mar 10, 2021

@augmentedfourth I pushed an amended commit (0c23a33) that fixes that issue. I added test cases to catch that now.

nojhan pushed a commit that referenced this issue Jan 5, 2022
This feature depends on the removal of the prompt escape sequences that
came before. Part of that is the removal of adding the title to $PS1:
now it is just print to the screen. This could improve speed slightly,
as the shell doesn't need to parse that text. But it does prevent usage
of prompt escape codes in the title.

Which causes a rare issue where __lp_escape() adds duplicate backslashes
or percents to escape a string for the prompt, but now are not needed in
the title. It will just print double in the title, so it isn't a huge
issue, but is something that should be fixed. I'm not sure how to handle
it though, since the current architecture requires escaping the strings
before formatting is added to them.

I also needed to rework how the runtime feature was handled, since it
monopolized the DEBUG trap in Bash. Now it can handle multiple features
that need to run after the user has submitted the command, but before it
runs.

The feature itself is simple: lookup the latest command in the history,
and print the normal title postpended by that command to the screen,
formatted as a terminal title. Note that Bash's $BASH_COMMAND is not
great, as it only contains the current _command_, not the whole command
line.

Resolves #609
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature request title Related to setting the terminal title
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants