I published this yesterday on github. It's a tmux plugin that scrapes
the active tmux pane for a magic wormhole code, then downloads and
optionally opens the file tied to the code. I wrote this to make it
easier to get pcaps from termshark into Wireshark. This plugin uses
gowid which itself depends wholly on tcell to manipulate the
terminal. Link: https://github.com/gcla/tmux-wormhole
Suspend call currently exits ca mode. So after the first suspend/resume
the program does not use the alternate screen anymore. Therefore Resume
needs to enter ca mode again.
fixes#194 Starting multiple screen sessions (lost key event)
You can test this by using the mouse demo, which now supports pressing
CTRL-Z. This does not actually suspend the demo, but starts a subshell
which takes over. After the subshell is exited, the demo takes control
of the screen back. This can be done multiple times, and it is possible
to start multiple "nested" iterations of the demo this way.
At some point in the future this is going to be replaced with
a simpler channel design, and the current blocking approach
is both non-idiomatic, and fragile. Don't use it.
This adds optional MouseFlags that can be used to adjust what is
tracked for mouse reporting (leaving the other modes to be handled
by the terminal.) This should work on all XTerm style terminals,
but on Windows we have no way to be selective here.
This does sort the main problem of screen.Fini(), but really we
want to use a separate Pause() and Resume() function, because
screen.Fini() is not meant for reuse in this way.
Note that one side effect of this change is that applications which
redirect stdin and stdout and expect us to just use /dev/tty instead
are going to break -- we are now using stdin and stdout like nearly
every other screen oriented application.
This adds Bracketed Paste support for terminals that have mouse
support and support it. The bracketing events are EventPaste,
with methods to note Start() or End() of the paste. Content
comes in as normal rune events. Programs must opt-in to this by
calling screen.EnablePaste().
@tslocum reported that the commit at 2d6d7fbe broke mouse support in
cview (https://github.com/gdamore/tcell/pull/384#issuecomment-698422464). The
purpose of the original commit was to fix a terminfo background color
code parsing problem that I spotted using TERM=xterm-16color:
$ infocmp xterm-16color | grep setab
setab=\E[%?%p1%{8}%<%t%p1%'('%+%e%p1%{92}%+%;%dm,
The middle sections says "if p1<8 then push(p1+'(') ". '(' is ascii
40. The sequence '%d' will then pop from the stack and interpreting the
result as an integer.
My change above was to have tcell assume the sequence between two single
quotes was a single ASCII character e.g. '(' and push that to the
terminfo stack as an integer with the ASCII value of the character
e.g. push(40:int). I didn't find any counterexamples in my local
terminfo database that didn't line up with that assumption; but I did
break mouse support because tcell generates its own rules to enable
mouse support, if not specified in the terminfo DB - both when
generating its own Golang-style internal DB, and in the dynamic terminfo
generator that uses infocmp:
"%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;\x1b[?1000%ga%c\x1b[?1002%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c"
This rule will push 'h' or 'l', depending on whether mouse mode is to be
enabled or disabled, and then sets the variable named a to the result,
interpreted as a string. The result is that when mouse mode is enabled,
tcell needs to emit \x1b[?1000h - where the 'h' comes from variable a
i.e. it needs to be able to push a quoted argument as a string and not
be forced into an int.
This alternative fix preserves the fact the quoted argument is a string
and maintains that on the stack. However, if the integer Pop() function
is called when the top element of the stack is a string, tcell will now
- return the string converted to an int, if it converts e.g. in the case
'123' is pushed to the stack as a string and popped as an int, the value
is 123
- otherwise return the ASCII value of the first character of the string
e.g. if '(' is pushed then popped as an int, the value returned is 40.
To be compatible with this logic, if a terminfo rule needs to push an
integer whose value is >= ascii('0')==48 and <= ascii('9')==57, it will
need to use the form e.g. {53} and not '5' because the form '5' will be
pushed as "5":string and if popped as an int will return the value 5 and
not 53.
I noticed this problem while running a gowid test program (palette.go)
with TERM=xterm-16color. This terminal type is not present in tcell's
built-in database, and so tcell falls back to the dynamic terminal type
by parsing the output of infocmp. The symptom was that foreground colors
were not correctly set, leaving a monochrome screen. This seems to be
caused by a problem interpreting the *background* color terminfo
rule. The attribute to set background color is defined like this (Ubuntu
20.04):
$ infocmp xterm-16color | grep setab
setab=\E[%?%p1%{8}%<%t%p1%'('%+%e%p1%{92}%+%;%dm,
The middle sections says "if p1<8 then push(p1+'(') ". '(' is ascii
40. If I run
$ tput setab 5
the terminal sees 'ESC[45m'. This correctly sets the background color to
magenta. But if I tell tcell to emit a cell with background color set to
tcell.Color(5), the terminal sees 'ESC[0m'. This means in practice, my
app emits a code to set the foreground color, then an SGR code that
resets all attributes, then the ASCII character.
When tcell "runs" a terminfo rule in terminfo::TParm(), a push to the
stack preserves the type of the argument pushed - int or string. When a
single quote is encountered, the argument within is pushed to the stack
as a string. For the `setab` rule above, tcell will then pop as an int,
discarding the error and returning 0. The fix here is to have tcell push
the argument inside the single quotes as an integer, using the ascii
value of the argument e.g. "(" -> 40 - and assume the string is length
1, I suppose. Cross-referencing against
ncurses/tinfo/lib_tinfo.c::tparam_internal(), it looks like this code
assumes a single-quoted string is assumed to be length=1 and is also
interpreted as an integer with the ascii value of the character:
case S_QUOTE:
cp++;
npush(UChar(*cp));
cp++;
break;