Compare commits

...

9 Commits
master ... 3.5a

Author SHA1 Message Date
Nicholas Marriott
549c35b061 Update regression tests. 2024-10-05 07:01:16 +01:00
Nicholas Marriott
42959db0a4 Update CHANGES. 2024-10-05 07:00:22 +01:00
Nicholas Marriott
7997fd3152 Missing define. 2024-10-04 18:59:53 +01:00
nicm
048db82041 Do not translate BSpace as Unicode, GitHub issue 4156. 2024-10-04 18:45:36 +01:00
nicm
356887bca2 Improve fix for shifted keys so it works for all the keys it should,
Stanislav Kljuhhin in GitHub issue 4146.
2024-10-03 08:14:32 +01:00
nicm
834ec91b44 Report shifted keys like S-A as A not as S-A in mode 1 extended keys,
from Stanislav Kljuhhin.
2024-10-02 11:06:53 +01:00
Nicholas Marriott
868ddf5d38 3.5a bits. 2024-09-30 13:09:50 +01:00
nicm
a1b7a3bcb3 Only use default-shell for popups, return to /bin/sh for run-shell,
if-shell and #() - these have been documented as using /bin/sh for a
long time and scripts rely on it. Pointed out by Gregory Pakosz.
2024-09-30 13:07:46 +01:00
nicm
cbd419c483 Fix grey colour, from Magnus Gross. 2024-09-30 13:06:55 +01:00
13 changed files with 103 additions and 67 deletions

11
CHANGES
View File

@ -1,3 +1,14 @@
CHANGES FROM 3.5 TO 3.5a
* Do not translate BSpace as Unicode with extended keys.
* Fix so that keys with Shift are represented correctly with extended keys.
* Revert to using /bin/sh for #() and run-shell and if-shell; the change to use
default-shell only applies now to popups.
* Fix grey colour without a number suffix in styles.
CHANGES FROM 3.4 TO 3.5 CHANGES FROM 3.4 TO 3.5
* Revamp extended keys support to more closely match xterm and support mode 2 * Revamp extended keys support to more closely match xterm and support mode 2

View File

@ -948,7 +948,7 @@ colour_byname(const char *name)
if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) { if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) {
if (name[4] == '\0') if (name[4] == '\0')
return (-1); return (0xbebebe|COLOUR_FLAG_RGB);
c = strtonum(name + 4, 0, 100, &errstr); c = strtonum(name + 4, 0, 100, &errstr);
if (errstr != NULL) if (errstr != NULL)
return (-1); return (-1);

View File

@ -1,6 +1,6 @@
# configure.ac # configure.ac
AC_INIT([tmux], 3.5) AC_INIT([tmux], 3.5a)
AC_PREREQ([2.60]) AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc) AC_CONFIG_AUX_DIR(etc)

23
job.c
View File

@ -69,9 +69,10 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
/* Start a job running. */ /* Start a job running. */
struct job * struct job *
job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s, job_run(const char *cmd, int argc, char **argv, struct environ *e,
const char *cwd, job_update_cb updatecb, job_complete_cb completecb, struct session *s, const char *cwd, job_update_cb updatecb,
job_free_cb freecb, void *data, int flags, int sx, int sy) job_complete_cb completecb, job_free_cb freecb, void *data, int flags,
int sx, int sy)
{ {
struct job *job; struct job *job;
struct environ *env; struct environ *env;
@ -81,6 +82,7 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e, struct sessio
sigset_t set, oldset; sigset_t set, oldset;
struct winsize ws; struct winsize ws;
char **argvp, tty[TTY_NAME_MAX], *argv0; char **argvp, tty[TTY_NAME_MAX], *argv0;
struct options *oo;
/* /*
* Do not set TERM during .tmux.conf (second argument here), it is nice * Do not set TERM during .tmux.conf (second argument here), it is nice
@ -91,12 +93,17 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e, struct sessio
if (e != NULL) if (e != NULL)
environ_copy(e, env); environ_copy(e, env);
if (s != NULL) if (~flags & JOB_DEFAULTSHELL)
shell = options_get_string(s->options, "default-shell");
else
shell = options_get_string(global_s_options, "default-shell");
if (!checkshell(shell))
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
else {
if (s != NULL)
oo = s->options;
else
oo = global_s_options;
shell = options_get_string(oo, "default-shell");
if (!checkshell(shell))
shell = _PATH_BSHELL;
}
argv0 = shell_argv0(shell, 0); argv0 = shell_argv0(shell, 0);
sigfillset(&set); sigfillset(&set);

View File

@ -717,7 +717,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
pd->job = job_run(shellcmd, argc, argv, env, s, cwd, pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd, popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette);
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,

View File

@ -22,8 +22,8 @@ $TMUX -f/dev/null new -d "
sleep 1 sleep 1
( (
printf '\033[1m\033[31m\033[42mabc\033[0m\033[31m\033[49mdef\n' printf '\033[1m\033[31m\033[42mabc\033[0m\033[31mdef\033[39m\n'
printf '\033[39m\033[100m bright bg\n' printf '\033[100m bright bg \033[49m\n'
) | cmp - $TMP || exit 1 ) | cmp - $TMP || exit 1
$TMUX has 2>/dev/null && exit 1 $TMUX has 2>/dev/null && exit 1

View File

@ -6,7 +6,7 @@
👍🏻3 👍🏻3
👍🏻 👍🏻4 👍🏻 👍🏻4
🤷5 🤷5
♂️ 7 7
🤷8 🤷8
🤷9 🤷9
🤷10 🤷10

View File

@ -172,7 +172,7 @@ test_format "#{l:#{pane_in_mode}}" "#{pane_in_mode}"
test_format "#{l:#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}}" "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}" test_format "#{l:#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}}" "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}"
# With escapes (which escape but are returned literally) # With escapes (which escape but are returned literally)
test_format "#{l:##{}" "##{" test_format "#{l:##{}" "#{"
test_format "#{l:#{#}}}" "#{#}}" test_format "#{l:#{#}}}" "#{#}}"
# Invalid formats: # Invalid formats:

View File

@ -6,10 +6,10 @@ TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) [ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest" TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null $TMUX kill-server 2>/dev/null
sleep 1
$TMUX -f/dev/null new -x20 -y2 -d || exit 1 $TMUX -f/dev/null new -x20 -y2 -d || exit 1
sleep 1
sleep 0.1 $TMUX set -g escape-time 0
exit_status=0 exit_status=0
@ -17,11 +17,14 @@ assert_key () {
key=$1 key=$1
expected_code=$2 expected_code=$2
$TMUX new-window -- sh -c 'stty raw -echo && cat -tv' W=$($TMUX new-window -P -- sh -c 'stty raw -echo && cat -tv')
$TMUX send-keys "$key" $ $TMUX send-keys -t$W "$key" 'EOL' || exit 1
sleep 0.2
actual_code=$($TMUX capturep -p | head -1 | sed -e 's/\$$//') actual_code=$($TMUX capturep -pt$W | \
$TMUX kill-window head -1 | \
sed -e 's/EOL.*$//')
$TMUX kill-window -t$W || exit 1
if [ "$actual_code" = "$expected_code" ]; then if [ "$actual_code" = "$expected_code" ]; then
if [ -n "$VERBOSE" ]; then if [ -n "$VERBOSE" ]; then
@ -205,7 +208,7 @@ assert_key 'PageUp' '^[[5~'
assert_key 'PgUp' '^[[5~' assert_key 'PgUp' '^[[5~'
assert_key 'BTab' '^[[Z' assert_key 'BTab' '^[[Z'
assert_key 'C-S-Tab' '^[[Z' assert_key 'C-S-Tab' '^I'
assert_key 'Up' '^[[A' assert_key 'Up' '^[[A'
assert_key 'Down' '^[[B' assert_key 'Down' '^[[B'
@ -291,8 +294,8 @@ assert_extended_key 'Insert' '^[[2;_~'
assert_extended_key 'DC' '^[[3;_~' assert_extended_key 'DC' '^[[3;_~'
assert_extended_key 'Delete' '^[[3;_~' assert_extended_key 'Delete' '^[[3;_~'
assert_key 'C-Tab' "^[[9;5u" assert_key 'C-Tab' "^[[27;5;9~"
assert_key 'C-S-Tab' "^[[1;5Z" assert_key 'C-S-Tab' "^[[27;6;9~"
$TMUX kill-server 2>/dev/null $TMUX kill-server 2>/dev/null

View File

@ -14,7 +14,7 @@ trap "rm -f $TMP" 0 1 15
$TMUX2 -f/dev/null new -d || exit 1 $TMUX2 -f/dev/null new -d || exit 1
$TMUX -f/dev/null new -d "$TMUX2 attach" || exit 1 $TMUX -f/dev/null new -d "$TMUX2 attach" || exit 1
sleep 0.1 sleep 1
exit_status=0 exit_status=0
@ -60,38 +60,38 @@ assert_key () {
} }
assert_key 0x00 'C-Space' # -- 'Escape 0x00' 'M-C-Space' assert_key 0x00 'C-Space' # -- 'Escape 0x00' 'C-M-Space'
assert_key 0x01 'C-a' -- 'Escape 0x01' 'M-C-a' assert_key 0x01 'C-a' -- 'Escape 0x01' 'C-M-a'
assert_key 0x02 'C-b' -- 'Escape 0x02' 'M-C-b' assert_key 0x02 'C-b' -- 'Escape 0x02' 'C-M-b'
assert_key 0x03 'C-c' -- 'Escape 0x03' 'M-C-c' assert_key 0x03 'C-c' -- 'Escape 0x03' 'C-M-c'
assert_key 0x04 'C-d' -- 'Escape 0x04' 'M-C-d' assert_key 0x04 'C-d' -- 'Escape 0x04' 'C-M-d'
assert_key 0x05 'C-e' -- 'Escape 0x05' 'M-C-e' assert_key 0x05 'C-e' -- 'Escape 0x05' 'C-M-e'
assert_key 0x06 'C-f' -- 'Escape 0x06' 'M-C-f' assert_key 0x06 'C-f' -- 'Escape 0x06' 'C-M-f'
assert_key 0x07 'C-g' -- 'Escape 0x07' 'M-C-g' assert_key 0x07 'C-g' -- 'Escape 0x07' 'C-M-g'
assert_key 0x08 'C-h' -- 'Escape 0x08' 'M-C-h' assert_key 0x08 'C-h' -- 'Escape 0x08' 'C-M-h'
assert_key 0x09 'Tab' -- 'Escape 0x09' 'M-Tab' assert_key 0x09 'Tab' -- 'Escape 0x09' 'M-Tab'
assert_key 0x0A 'C-j' -- 'Escape 0x0A' 'M-C-j' assert_key 0x0A 'C-j' -- 'Escape 0x0A' 'C-M-j'
assert_key 0x0B 'C-k' -- 'Escape 0x0B' 'M-C-k' assert_key 0x0B 'C-k' -- 'Escape 0x0B' 'C-M-k'
assert_key 0x0C 'C-l' -- 'Escape 0x0C' 'M-C-l' assert_key 0x0C 'C-l' -- 'Escape 0x0C' 'C-M-l'
assert_key 0x0D 'Enter' -- 'Escape 0x0D' 'M-Enter' assert_key 0x0D 'Enter' -- 'Escape 0x0D' 'M-Enter'
assert_key 0x0E 'C-n' -- 'Escape 0x0E' 'M-C-n' assert_key 0x0E 'C-n' -- 'Escape 0x0E' 'C-M-n'
assert_key 0x0F 'C-o' -- 'Escape 0x0F' 'M-C-o' assert_key 0x0F 'C-o' -- 'Escape 0x0F' 'C-M-o'
assert_key 0x10 'C-p' -- 'Escape 0x10' 'M-C-p' assert_key 0x10 'C-p' -- 'Escape 0x10' 'C-M-p'
assert_key 0x11 'C-q' -- 'Escape 0x11' 'M-C-q' assert_key 0x11 'C-q' -- 'Escape 0x11' 'C-M-q'
assert_key 0x12 'C-r' -- 'Escape 0x12' 'M-C-r' assert_key 0x12 'C-r' -- 'Escape 0x12' 'C-M-r'
assert_key 0x13 'C-s' -- 'Escape 0x13' 'M-C-s' assert_key 0x13 'C-s' -- 'Escape 0x13' 'C-M-s'
assert_key 0x14 'C-t' -- 'Escape 0x14' 'M-C-t' assert_key 0x14 'C-t' -- 'Escape 0x14' 'C-M-t'
assert_key 0x15 'C-u' -- 'Escape 0x15' 'M-C-u' assert_key 0x15 'C-u' -- 'Escape 0x15' 'C-M-u'
assert_key 0x16 'C-v' -- 'Escape 0x16' 'M-C-v' assert_key 0x16 'C-v' -- 'Escape 0x16' 'C-M-v'
assert_key 0x17 'C-w' -- 'Escape 0x17' 'M-C-w' assert_key 0x17 'C-w' -- 'Escape 0x17' 'C-M-w'
assert_key 0x18 'C-x' -- 'Escape 0x18' 'M-C-x' assert_key 0x18 'C-x' -- 'Escape 0x18' 'C-M-x'
assert_key 0x19 'C-y' -- 'Escape 0x19' 'M-C-y' assert_key 0x19 'C-y' -- 'Escape 0x19' 'C-M-y'
assert_key 0x1A 'C-z' -- 'Escape 0x1A' 'M-C-z' assert_key 0x1A 'C-z' -- 'Escape 0x1A' 'C-M-z'
assert_key 0x1B 'Escape' -- 'Escape 0x1B' 'M-Escape' assert_key 0x1B 'Escape' -- 'Escape 0x1B' 'M-Escape'
assert_key 0x1C "C-\\" -- 'Escape 0x1C' "M-C-\\" assert_key 0x1C "C-\\" -- 'Escape 0x1C' "C-M-\\"
assert_key 0x1D 'C-]' -- 'Escape 0x1D' 'M-C-]' assert_key 0x1D 'C-]' -- 'Escape 0x1D' 'C-M-]'
assert_key 0x1E 'C-^' -- 'Escape 0x1E' 'M-C-^' assert_key 0x1E 'C-^' -- 'Escape 0x1E' 'C-M-^'
assert_key 0x1F 'C-_' -- 'Escape 0x1F' 'M-C-_' assert_key 0x1F 'C-_' -- 'Escape 0x1F' 'C-M-_'
assert_key 0x20 'Space' -- 'Escape 0x20' 'M-Space' assert_key 0x20 'Space' -- 'Escape 0x20' 'M-Space'
assert_key 0x21 '!' -- 'Escape 0x21' 'M-!' assert_key 0x21 '!' -- 'Escape 0x21' 'M-!'
assert_key 0x22 '"' -- 'Escape 0x22' 'M-"' assert_key 0x22 '"' -- 'Escape 0x22' 'M-"'
@ -304,7 +304,7 @@ assert_extended_key () {
key_name=$2 key_name=$2
assert_key "Escape [${code};5u" "C-$key_name" assert_key "Escape [${code};5u" "C-$key_name"
assert_key "Escape [${code};7u" "M-C-$key_name" assert_key "Escape [${code};7u" "C-M-$key_name"
} }
# Extended keys # Extended keys

4
tmux.c
View File

@ -408,9 +408,9 @@ main(int argc, char **argv)
cfg_files[cfg_nfiles++] = xstrdup(optarg); cfg_files[cfg_nfiles++] = xstrdup(optarg);
cfg_quiet = 0; cfg_quiet = 0;
break; break;
case 'V': case 'V':
printf("tmux %s\n", getversion()); printf("tmux %s\n", getversion());
exit(0); exit(0);
case 'l': case 'l':
flags |= CLIENT_LOGIN; flags |= CLIENT_LOGIN;
break; break;

1
tmux.h
View File

@ -2341,6 +2341,7 @@ typedef void (*job_free_cb) (void *);
#define JOB_NOWAIT 0x1 #define JOB_NOWAIT 0x1
#define JOB_KEEPWRITE 0x2 #define JOB_KEEPWRITE 0x2
#define JOB_PTY 0x4 #define JOB_PTY 0x4
#define JOB_DEFAULTSHELL 0x8
struct job *job_run(const char *, int, char **, struct environ *, struct job *job_run(const char *, int, char **, struct environ *,
struct session *, const char *, job_update_cb, struct session *, const char *, job_update_cb,
job_complete_cb, job_free_cb, void *, int, int, int); job_complete_cb, job_free_cb, void *, int, int, int);

View File

@ -930,7 +930,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
u_int number, modifiers; u_int number, modifiers;
char tmp[64]; char tmp[64];
cc_t bspace; cc_t bspace;
key_code nkey; key_code nkey, onlykey;
struct utf8_data ud; struct utf8_data ud;
utf8_char uc; utf8_char uc;
@ -983,7 +983,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
nkey = number; nkey = number;
/* Convert UTF-32 codepoint into internal representation. */ /* Convert UTF-32 codepoint into internal representation. */
if (nkey & ~0x7f) { if (nkey != KEYC_BSPACE && nkey & ~0x7f) {
if (utf8_fromwc(nkey, &ud) == UTF8_DONE && if (utf8_fromwc(nkey, &ud) == UTF8_DONE &&
utf8_from_data(&ud, &uc) == UTF8_DONE) utf8_from_data(&ud, &uc) == UTF8_DONE)
nkey = uc; nkey = uc;
@ -994,13 +994,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
/* Update the modifiers. */ /* Update the modifiers. */
if (modifiers > 0) { if (modifiers > 0) {
modifiers--; modifiers--;
/* if (modifiers & 1)
* The Shift modifier may not be reported in some input modes,
* which is unfortunate, as in general case determining if a
* character is shifted or not requires knowing the input
* keyboard layout. So we only fix up the trivial case.
*/
if (modifiers & 1 || (nkey >= 'A' && nkey <= 'Z'))
nkey |= KEYC_SHIFT; nkey |= KEYC_SHIFT;
if (modifiers & 2) if (modifiers & 2)
nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */ nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */
@ -1014,6 +1008,26 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT)) if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT))
nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT); nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT);
/*
* Deal with the Shift modifier when present alone. The problem is that
* in mode 2 some terminals would report shifted keys, like S-a, as
* just A, and some as S-A.
*
* Because we need an unambiguous internal representation, and because
* restoring the Shift modifier when it's missing would require knowing
* the keyboard layout, and because S-A would cause a lot of issues
* downstream, we choose to lose the Shift for all printable
* characters.
*
* That still leaves some ambiguity, such as C-S-A vs. C-A, but that's
* OK, and applications can handle that.
*/
onlykey = nkey & KEYC_MASK_KEY;
if (((onlykey > 0x20 && onlykey < 0x7f) ||
KEYC_IS_UNICODE(nkey)) &&
(nkey & KEYC_MASK_MODIFIERS) == KEYC_SHIFT)
nkey &= ~KEYC_SHIFT;
if (log_get_level() != 0) { if (log_get_level() != 0) {
log_debug("%s: extended key %.*s is %llx (%s)", c->name, log_debug("%s: extended key %.*s is %llx (%s)", c->name,
(int)*size, buf, nkey, key_string_lookup_key(nkey, 1)); (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));