Skip to content
44 changes: 29 additions & 15 deletions src/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,6 @@ init_display(void)
{
bool no_display = !!getenv("TIG_NO_DISPLAY");
const char *term;
int x, y;

if (!opt_tty.file)
die("Can't initialize display without tty");
Expand All @@ -621,30 +620,45 @@ init_display(void)
die("Failed to register done_display");

/* Initialize the curses library */
if (!no_display && isatty(STDIN_FILENO)) {
if (no_display) {
FILE *null_file = fopen("/dev/null", "w+");

/* endwin() must not be called out of last-to-first order on instantiated
* SCREENs. Not typically an issue, since after this block, tig will not
* leave output_scr. */
SCREEN *input_scr = newterm(NULL, opt_tty.file, opt_tty.file);
SCREEN *output_scr = newterm(NULL, null_file, null_file);

if (!(cursed = input_scr && output_scr))
die("Failed to initialize curses");

set_term(input_scr);
/* buglet: unsafe for signals over next 5 statements due to endwin() in
* done_display(). */
raw();
nonl();
noecho();
status_win = newwin(1, 1, 0, 0);
set_term(output_scr);
} else if (isatty(STDIN_FILENO)) {
/* Needed for ncurses 5.4 compatibility. */
cursed = !!initscr();
} else {
/* Leave stdin and stdout alone when acting as a pager. */
FILE *out_tty;
int x, y;

out_tty = no_display ? fopen("/dev/null", "w+") : opt_tty.file;
if (!out_tty)
die("Failed to open tty for output");
cursed = !!newterm(NULL, out_tty, opt_tty.file);
if (!(cursed = !!newterm(NULL, opt_tty.file, opt_tty.file)))
die("Failed to initialize curses");

getmaxyx(stdscr, y, x);
status_win = newwin(1, x, y - 1, 0);
}

if (!cursed)
die("Failed to initialize curses");
if (!status_win)
die("Failed to create status window");

set_terminal_modes();
init_colors();

getmaxyx(stdscr, y, x);
status_win = newwin(1, x, y - 1, 0);
if (!status_win)
die("Failed to create status window");

/* Enable keyboard mapping */
keypad(status_win, true);
wbkgdset(status_win, get_line_attr(NULL, LINE_STATUS));
Expand Down
58 changes: 58 additions & 0 deletions test/API.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,64 @@ tig_script(name, content, [content, ...])::

steps(content, [content, ...])::

keystrokes([-append | -keysym | -repeat=<int>] key-sequence, [key-sequence, ...])::

Key sequences are given as Python strings, and accept
https://docs.python.org/2.0/ref/strings.html[the same string escapes as
Python]. Example: `'\134'` encodes a literal backslash. +
+
The key sequence may also contain special embedded codes:
`%(keysym:<name>)`, `%(keypause:<seconds>)`, or `%(keysignal:<signal>)`. +
+
*`%(keysym:<name>)`* will be translated into the raw characters
associated with the symbolic key name. <name> may be any form accepted
by 'bind' in `~/.tigrc`, or any terminal capability name known to
`tput`. Examples: `%(keysym:Left)`, `%(keysym:Ctrl-A)`. +
+
As a convenience, the `-keysym` option causes subsequent arguments to
be interpreted as a series of keysym names. Example:
-----------------------------------------------------------------------------
keystrokes -keysym 'Down' 'Up'
-----------------------------------------------------------------------------
::
*`%(keypause:<seconds>)`* will insert a pause in the simulated
keystrokes. If pauses are added, the test timeout may also need to be
increased. +
+
*`%(keysignal:<signal>)`* will send a Unix signal to tig. The signal
may be given as a number or symbol. Example: `%(keysignal:SIGWINCH)` +
+
To send tig a literal sequence matching the characters of an embedded
code, escape it with a backslash: `\%(keypause:1)`. +
+
Exiting: The passed key sequence should always arrange a clean exit.
Tig will otherwise be shut down by a signal, which is less consistent
for the purpose of testing. +
+
Appending: keystrokes may be defined in multiple passes using `-append`.
This enables composing keystrokes with and without `-keysym`. The last
call to `keystrokes()` should arrange a clean exit from tig. +
+
Repeating: `-repeat=<int>` can be used to define repeated sequences.
Only one key-sequence argument may be used with `-repeat`. Example:
-----------------------------------------------------------------------------
keystrokes -keysym -repeat=20 'Down'
-----------------------------------------------------------------------------
::
Interaction with `steps()`: It is possible to use both `steps()` and
`keystrokes()` in the same test: during test execution, the `steps()`
script will run first, and the simulated keystrokes will be sent to tig
after the script finishes. When used together, `steps()` is modified so
that it does not imply `:quit`. +
+
Whitespace handling: The "Enter" key will be fed to tig as a carriage
return (`\r`). Interior newlines in key sequences, whether literal or
encoded, will be translated to carriage returns before sending them to
tig. But note that leading or trailing whitespace on the key-sequence
argument is ignored. To send "Enter", "Tab", or "Space" as the first or
last key in the sequence, use escape codes or keysyms (_ie_ `\r`,`\t`,
`\040`, `%(keysym:Enter)`, `%(keysym:Tab)`, or `%(keysym:Space)`.) +

stdin([content, ...]) [< content]::

tigrc([content, ...]) [< content]::
Expand Down
6 changes: 5 additions & 1 deletion test/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ filter=<file-glob>:<case-glob>::

trace::

Show trace information.
Show tig trace information.

trace_keys::

Show which keystrokes will be sent before each test.

todos::

Expand Down
2 changes: 0 additions & 2 deletions test/diff/diff-highlight-color-test
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

test_require diff-highlight

export PATH="$(dirname -- "$diff_highlight_path"):$PATH"

gitconfig <<EOF
[color.diff-highlight]
oldnormal=red bold
Expand Down
51 changes: 51 additions & 0 deletions test/prompt/history-cases-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/sh

. libtest.sh
. libgit.sh

export LINES=3
export COLUMNS=80

test_require readline

in_work_dir create_repo_from_tgz "$base_dir/files/scala-js-benchmarks.tgz"

test_case one \
--before='rm -f -- "$HOME/.tig_history"' \
--tigrc='set history-size = 10' \
--keystrokes=':echo keys_one\r:quit\r' \
--assert-equals=".tig_history"='echo keys_one
quit
' \
<<EOF
2014-03-01 17:26 -0500 Jonas Fonseca o [master] WIP: Upgrade to 0.4-SNAPSHO
[main] ee912870202200a0b9cf4fd86ba57243212d341e - commit 1 of 48 2%
EOF

test_case two \
--before='rm -f -- "$HOME/.tig_history"' \
--tigrc='set history-size = 10' \
--keystrokes=':echo keys_two\r:quit\r' \
--assert-equals=".tig_history"="echo keys_two
quit
" \
--script=':echo first_line
:echo second_line' \
<<EOF
2014-03-01 17:26 -0500 Jonas Fonseca o [master] WIP: Upgrade to 0.4-SNAPSHO
[main] ee912870202200a0b9cf4fd86ba57243212d341e - commit 1 of 48 2%
EOF

test_case three \
--before='rm -f -- "$HOME/.tig_history"' \
--tigrc='set history-size = 10' \
--keystrokes=':echo keys_four\r:quit\r' \
--assert-equals=".tig_history"='echo keys_four
quit
' \
<<EOF
2014-03-01 17:26 -0500 Jonas Fonseca o [master] WIP: Upgrade to 0.4-SNAPSHO
[main] ee912870202200a0b9cf4fd86ba57243212d341e - commit 1 of 48 2%
EOF

run_test_cases
30 changes: 30 additions & 0 deletions test/prompt/history-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

. libtest.sh
. libgit.sh

export LINES=3
export COLUMNS=80

test_require readline

in_work_dir create_repo_from_tgz "$base_dir/files/scala-js-benchmarks.tgz"

tigrc <<EOF
set history-size = 3
EOF

keystrokes ':none'
keystrokes -append -keysym 'Enter'
keystrokes -append ':quit'
keystrokes -append -keysym 'Enter'

test_tig

assert_equals stderr <<EOF
EOF

assert_equals "$HOME/.tig_history" <<EOF
none
quit
EOF
43 changes: 43 additions & 0 deletions test/tigrc/script-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/sh

. libtest.sh
. libgit.sh

LINES=12
COLUMNS=200

in_work_dir create_repo_from_tgz "$base_dir/files/scala-js-benchmarks.tgz"

export TIGRC_SYSTEM=does-not-exist

file "$HOME/.tigrc.bind.q.for.help.screen" <<EOF
:bind generic q quit
:view-help
:save-display $HOME/help.screen
EOF

tigrc <<EOF
bind generic : prompt # Must have prompt mapping to execute script
bind generic S :script $HOME/.tigrc.bind.q.for.help.screen
EOF

keystrokes 'Sq'

test_tig

assert_equals stderr <<EOF
EOF

assert_equals "$HOME/help.screen" <<EOF
Quick reference for tig keybindings:

[-] generic bindings
View manipulation
q quit Close all views and quit
Misc
: prompt Open the prompt
Internal commands:
S :script $HOME/.tigrc.bind.q.for.help.screen

[help] - line 1 of 9 100%
EOF
Loading