How to print colored text below the prompt in zsh widget?
Asked Answered
T

1

7

I want to create a widget bound to a hotkey that prints the current command description in rich text below the prompt, then erases it after a keypress. Like so (simplified):

widget() {
  zle -R "ls - list files"
  read -k 1
}
zle -N widget
bindkey '\eg' widget

But zle -R can print only plain text, it doesn't even support line breaks. I want to print text with color and line breaks like ^[[31mls^[[00m - list files.

What approaches can I use to do that?

Just printing it to a regular stdout then initializing a new prompt would be a bad user interface for my use case. That would be an undesirable solutions.

I want it to appear below the prompt and work similarly to zsh-autocomplete, ctrl+R, or fzf. The output doesn't have any complex interactions, it only appears on hotkey and disappears on keypress after that.

The zsh-autocomplete repo does similar, but I don’t know how it is done.

Tulley answered 5/3, 2023 at 9:46 Comment(7)
zle -R $'\e[31mls\e[00m - list files' doesn't work?Cumin
No, it can only print plain text. Control codes will show up in terminal.Tulley
You said that even linebreaks don't work; did you try with a literal one? zle -R $'ls - \n list files'Cumin
Yes I did. If you want to suggest that my statements are false, it's a good idea to test your claims first.Tulley
you provided an example but I don’t know how to use it; btw, a literal newline isn’t '\n' but $'\n'; because you didn't comment on that construct I wasn't sure that you tested it, sorry for thatCumin
zle -R can't output any kind of control characters, at least that was the case at the time of this thread (which is pretty old to be fair)Tulley
I'm not a master on zsh, but I know a few things. I spend a few hours on this one and I couldn't find something. Maybe an expert could help.Eastbourne
D
3

When you use zle -R, you end up calling this function inside zsh. The first argument after -R is stored in statusline. That is checked here and stripped of any characters that would modify the screen unexpectedly here. So the mailing list question from 2011 is still present today.

Upon review of the hooks and the code in zsh-autocomplete, I now understand this works by using built in support for color highlighting in zsh while actively using autocomplete.

Since you just wish to have a key binding to display the status line and await for a keystroke, you will need to write (in C) a module to display the current BUFFER and await a keystroke. This will require you to track the cursor position and maintaining the same state that zsh is expecting.

The example module is a start. You will need to compile it with zsh, as the build script builds all modules with tools needed to create the .mdh/.pro files from the .mdd of your module.

Here is an updated widget that demonstrates the various options:

widget() {
  autoload -Uz colors && colors
  PREDISPLAY="PRE:"
  POSTDISPLAY="${fg[red]}POST$reset_color"
  zle -R "$BUFFER" "${fg[red]}line below$reset_color"
  print "${fg[red]}print$reset_color"
  read -k 1
}
zle -N widget

Notice, you can't control the display of the status line, it has all special characters removed. The print properly allows special characters, but only on the input line (not on the status line). PRE/POST also only work on the input line, and also are stripped of special characters.

What approaches can I use to do that?

  • Write your own module. This is the best way.
  • you may be able to use print to color it as you wish, but you would need to still make sure the screen positions are maintained as zsh expects.
Deutero answered 20/3, 2023 at 3:46 Comment(2)
This answer states that zsh-autocomplete manages to do it, but doesn't really explain how apart from "it adds some hooks that do the thing". Can you explain what functions does it use to print the text? I already tried to dive into zsh-autocomplete repo but it's too complex for me to find the relevant parts.Tulley
I think it could be done at least with some clever printing into the current buffer and erasing it after keypress.Tulley

© 2022 - 2024 — McMap. All rights reserved.