3

I have a program that I'd like to run, deluding it to believe that my terminal has less columns than it does, because that enables its native truncation, which I need.

I tried resize from xterm as suggested on askubuntu, however, that only works properly within xterm and can hardly be scripted. I need something that I can use within a script to get the output of a taskwarrior command.

Exporting a different value for COLUMNS doesn't seem to change anything unfortunately.

1
  • 1
    downvoter, care to explain?
    – xeruf
    Commented Oct 24, 2020 at 17:25

3 Answers 3

3

The community answer is on the right track.

You can use tmux to create a detached session with the geometry that you want (column width, assume some number of rows).

tmux new-session -d -s task-session -x WIDTH -y HEIGHT

Then run your command.

tmux send-keys 'task' ENTER

Do not pipe command output to a file.

Dump the tmux pane to file:

tmux capture-pane -b temp-buffer -S -
tmux save-buffer -b temp-buffer output.txt
tmux delete-buffer -b temp-buffer 

Reference

3
  • hm yeah that is what I feared ^^ could you elaborate please?
    – xeruf
    Commented Oct 24, 2020 at 17:26
  • The tmux man page is fairly well-written, but there's a lot there. I've updated my answer with actual commands. Commented Oct 24, 2020 at 18:50
  • Thank you, I tried many dead ends before I found this solution! I ran into a little trouble with buffers, and I got a buffer invalid error trying this code. But I found that capture-pane has a -p flag to print the buffer to stdout. The command that worked for me: tmux capture-pane -t ${tmux_session}.0 -pe -S -500. Commented Nov 19, 2022 at 3:08
2

The POSIX standard is, indeed, that the value of the COLUMNS environment variable supersedes other ways of obtaining the terminal size. The standard describes one of the variable's purposes as "display[ing] data in an area arbitrarily smaller than the terminal or window" amongst other things, which matches what you want.

Those other ways are not standardized, but they are commonly an ioctl() of TIOCGWINSZ against a terminal device open file descriptor. Your program does this; albeit that it just assumes without isatty() checks that its standard output is a terminal device.

Unfortunately, there are programs that do not respect the COLUMNS environment variable and yours is sadly one of them. Instead it provides is own idiosyncratic non-standard mechanism, the detection and defaultwidth settings in its configuration file.

Adding to the sadness is that these operate the other way around to the COLUMNS environment variable. They are a fallback, not an override. You have to turn detection off, so that the program stops using TIOCGWINSZ and falls back to the default. You have to then set a value for defaultwidth, which is 80 if unset and 65536 with detection forced off if zero.

Further addition to the sadness is that turning detection off applies to both width and height, unlike the POSIX standard COLUMNS and LINES variables which operate independently of each other. So you have to concern yourself with a defaultheight as well, which is 24 if unset and 65536 with detection forced off if zero.

You could, alternatively, leave detection on and fool your program with a pseudo-terminal instead. tmux is a complex way to achieve this, with all that key stuffing and intermediary file use. Using Bernstein ptybandage and stty columns (against the internal pseudo-terminal) is simpler, takes one line, and outputs to standard output in real time as your program is running:

ptybandage sh -c 'stty columns 40 ; exec task'

Further reading

  • Daniel J. Bernstein (1996). ptybandage. djbwares.
  • Jonathan de Boyne Pollard (2014). ptybandage. nosh Guide. Softwares.
1
  • As indicated in the linked documentation, ptybandage is superceded by execlineb which is part of the execline package in the AUR
    – xeruf
    Commented Nov 30, 2021 at 8:25
1

The following does not yet work, but I suspect that you could make it work with some modifications. The commands create a new tmux session and modify the size of the pane before executing taskwarrior:

tmux new -d -s s1
tmux split -v
tmux resize-pane -t s1 -y 5
tmux send-keys "task > output.txt" ENTER
sleep 1
tmux kill-session -t s1
cat output.txt

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .