0

How do I change the width of a tab, for indentation, in single- and multi-line commands in ZSH? This is not the same as literal tabs; when you hit the tab key, ZSH actually emit spaces to the terminal:

zsh -f # Run without config
blackcap% echo $'\t.'
        .
blackcap%       .
blackcap% if
if>     .
blackcap% tabs 4
blackcap% echo $'\t.'
    .
blackcap%       .
blackcap% if
if>     .

This behavior is not affected by settings in my terminal emulator, setterm --regtabs, nor by the promising-sounding IFS variable mentioned in man zshparam.

I could obviously write my own version and bind it to tab, but this last-resort quickly gets hairy when the cursor is moved, lines wrap, there are more than one line- not to mention >> and friends with vi-keys.

BlackCap
  • 261
  • 1
  • 3
  • 10

2 Answers2

1

stty -a would show you if the terminal's setup to use hardware tabs (which can be programmed) or not (look for tab0 in the output).

zsh might be hardcoded; setterm certainly is (see this). It would happen to work if your terminal is setup for hardware tabs. But the tabs program isn't hardcoded (and is probably installed on your machine).

enter image description here

Thomas Dickey
  • 76,765
  • I am furiously browsing the zsh source code hoping to prove it is indeed hard-coded. I'll accept this once I give up! – BlackCap Mar 23 '20 at 01:02
  • As you can see from the screenshot, the echoes (adapted from the question) worked for me. – Thomas Dickey Mar 23 '20 at 08:01
  • If you look at my example, literal tabs did work for me too. The problem is that zsh emit spaces not tabs when you press tab key- and my question is can I configure the number of spaces it emits? – BlackCap Mar 23 '20 at 22:17
1

ZLE expands TAB characters in prompt strings and input command-lines to spaces on display. The expansion uses a fixed calculation of tabstops every 8 columns, and does not involve emitting the actual TAB character to the terminal and thus your terminal's actual tabstop settings. It makes the same assumption when it uses TAB as a shortcut for rightwards cursor motion, when it is told by the terminfo/termcap database that it does not have a parameterized cursor forward control sequence. (example, example, example)

You got lucky with tabs. In general, do not use the util-linux setterm in any terminal emulator other than the built-in Linux one, that drives Linux KVTs. See https://unix.stackexchange.com/a/491883/5132 for a portable workalike that does not hard-code the Linux built-in terminal emulator's control sequences.

JdeBP
  • 68,745
  • Zsh does not expand tab characters, either in prompt strings or input command-lines. You can confirm this by selecting the text containing the tab with the mouse which zsh has zero visibility of. In effect, this is purely a matter for the terminal emulator configuration. – okapi Mar 23 '20 at 10:26
  • Actually, by doing that with the partial if in the question one can confirm exactly the opposite, which is unsurprising given what one can see in the source code pointed to. – JdeBP Mar 23 '20 at 10:40
  • This is my understanding after staring at the code too. Looking at viindent (>> with vi-keys) in zle_vi.c we find that it indents with a literal tab, but this is expanded later down the line. It is hard to tell what is expansion, what is cursor movement, and what is their indentation atom (which uses the bitmask (x | 7)). I was unable to pin it down to one location through testing. – BlackCap Mar 23 '20 at 22:11