From 0c11542eca1dece642c66b7289097e415dc7fc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 23 Jul 2020 18:56:47 +0200 Subject: [PATCH 01/24] changelog: add new 'unreleased' section --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9bcb1ab..94b82f4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#unreleased) * [1.4.2](#1.4.2) * [1.4.1](#1-4-1) * [1.4.0](#1-4-0) @@ -9,6 +10,14 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) +## Unreleased +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security + ## 1.4.2 From cc60d3a6701d2266eda30bdad6cebc67d05bcc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 17:46:18 +0200 Subject: [PATCH 02/24] csi: primary DA: remove features we do not support We do not implement * Selective Erase * Technical Character Set * Terminal state interrogation --- CHANGELOG.md | 3 +++ csi.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94b82f4a..be481757 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ ## Unreleased ### Added ### Changed + +* Primary DA to no longer indicate support for _Selective Erase_, + _Technical Characters_ and _Terminal State Interrogation_. ### Deprecated ### Removed ### Fixed diff --git a/csi.c b/csi.c index fe102ada..044c6e3f 100644 --- a/csi.c +++ b/csi.c @@ -373,8 +373,17 @@ csi_dispatch(struct terminal *term, uint8_t final) * - 22 ANSI color, e.g., VT525. * - 28 Rectangular editing. * - 29 ANSI text locator (i.e., DEC Locator mode). + * + * Note: we report ourselves as a VT220, mainly to be able + * to pass parameters, to indiciate we support sixel, and + * ANSI colors. + * + * The VT level must be synchronized with the secondary DA + * response. + * + * Note: tertiary DA responds with "FOOT". */ - const char *reply = "\033[?62;4;6;15;17;22c"; + const char *reply = "\033[?62;4;22c"; term_to_slave(term, reply, strlen(reply)); break; } From 60984e7a2476e81ffe9d356d6e4cb11e218d812e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 17:47:47 +0200 Subject: [PATCH 03/24] csi: secondary DA: do not pretend we're xterm Previously, our secondary DA response indicated a) VT420, b) an XTerm version number. Now, we indicate VT220 (which corresponds to the primary DA response), and we report foot's version number as MMmmpp. I.e major, minor and patch versions, using two digits. E.g. 1.4.2 is encoded as 010402 --- CHANGELOG.md | 7 +++++++ csi.c | 18 ++++++++++++++++-- generate-version.sh | 9 ++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be481757..2d2138b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,13 @@ * Primary DA to no longer indicate support for _Selective Erase_, _Technical Characters_ and _Terminal State Interrogation_. +* Secondary DA to report foot as a VT220 instead of a VT420. +* Secondary DA to report foot's version number in parameter 2, the + _Firmware Version_. The string is made up of foot's major, minor and + patch version numbers, always using two digits for each version + number and without any other separating characters. Thus, _1.4.2_ + would be reported as `010402` (i.e. the full response would be + `\E[>1;010402;0c`). ### Deprecated ### Removed ### Fixed diff --git a/csi.c b/csi.c index 044c6e3f..2122d272 100644 --- a/csi.c +++ b/csi.c @@ -13,10 +13,11 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "grid.h" -#include "vt.h" #include "selection.h" #include "sixel.h" #include "util.h" +#include "version.h" +#include "vt.h" #define UNHANDLED() LOG_DBG("unhandled: %s", csi_as_string(term, final, -1)) #define UNHANDLED_SGR(idx) LOG_DBG("unhandled: %s", csi_as_string(term, 'm', idx)) @@ -1414,9 +1415,22 @@ csi_dispatch(struct terminal *term, uint8_t final) * xterm uses its version number. We use an xterm * version number too, since e.g. Emacs uses this to * determine level of support. + * + * We report ourselves as a VT220. This must be + * synchronized with the primary DA respons. + * + * Note: tertiary DA replies with "FOOT". */ - term_to_slave(term, "\033[>41;347;0c", 12); + static_assert(FOOT_MAJOR < 100, "Major version must not exceed 99"); + static_assert(FOOT_MINOR < 100, "Minor version must not exceed 99"); + static_assert(FOOT_PATCH < 100, "Patch version must not exceed 99"); + + char reply[64]; + snprintf(reply, sizeof(reply), "\033[>1;%02u%02u%02u;0c", + FOOT_MAJOR, FOOT_MINOR, FOOT_PATCH); + + term_to_slave(term, reply, strlen(reply)); break; case 'm': diff --git a/generate-version.sh b/generate-version.sh index ecd0306f..cfb85059 100755 --- a/generate-version.sh +++ b/generate-version.sh @@ -22,7 +22,14 @@ else new_version="${default_version}" fi -new_version="#define FOOT_VERSION \"${new_version}\"" +major=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1/') +minor=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\2/') +patch=$(echo "${new_version}" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\3/') + +new_version="#define FOOT_VERSION \"${new_version}\" +#define FOOT_MAJOR ${major} +#define FOOT_MINOR ${minor} +#define FOOT_PATCH ${patch}" if [ -f "${out_file}" ]; then old_version=$(cat "${out_file}") From 8d81dde5b8ba0d0b694794c0a223c76cfcff5335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 17:49:50 +0200 Subject: [PATCH 04/24] search: improve viewport movements * Don't move the viewport if the new match is already fully visible * When we do have to move the viewport, position it such that the new match ends up roughly in the middle. --- CHANGELOG.md | 6 ++++ search.c | 78 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d2138b6..9dc70f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,12 @@ number and without any other separating characters. Thus, _1.4.2_ would be reported as `010402` (i.e. the full response would be `\E[>1;010402;0c`). +* Scrollback search to only move the viewport if the match lies + outside it. +* Scrollback search to focus match, that requires a viewport change, + roughly in the center of the screen. + + ### Deprecated ### Removed ### Fixed diff --git a/search.c b/search.c index 7786937a..e02aaa7c 100644 --- a/search.c +++ b/search.c @@ -104,8 +104,52 @@ search_update_selection(struct terminal *term, int start_row, int start_col, int end_row, int end_col) { + /* Selection endpoint is inclusive */ + if (--end_col < 0) { + end_col = term->cols - 1; + end_row--; + } + + /* Begin a new selection if the start coords changed */ + if (start_row != term->search.match.row || + start_col != term->search.match.col) + { + int selection_row = start_row - term->grid->view; + while (selection_row < 0) + selection_row += term->grid->num_rows; + + assert(selection_row >= 0 && + selection_row < term->grid->num_rows); + selection_start(term, start_col, selection_row, SELECTION_NORMAL); + } + + /* Update selection endpoint */ + { + int selection_row = end_row - term->grid->view; + while (selection_row < 0) + selection_row += term->grid->num_rows; + + assert(selection_row >= 0 && + selection_row < term->grid->num_rows); + selection_update(term, end_col, selection_row); + } + + int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1); + if (view_end >= term->grid->view) { + /* Viewport does *not* wrap around */ + if (start_row >= term->grid->view && end_row <= view_end) + return; + } else { + /* Viewport wraps */ + if (start_row >= term->grid->view || end_row <= view_end) + return; + } + int old_view = term->grid->view; - int new_view = start_row; + int new_view = start_row - term->rows / 2; + + while (new_view < 0) + new_view += term->grid->num_rows; /* Prevent scrolling in uninitialized rows */ bool all_initialized = false; @@ -137,36 +181,6 @@ search_update_selection(struct terminal *term, term->grid->view = new_view; if (new_view != old_view) term_damage_view(term); - - /* Selection endpoint is inclusive */ - if (--end_col < 0) { - end_col = term->cols - 1; - end_row--; - } - - /* Begin a new selection if the start coords changed */ - if (start_row != term->search.match.row || - start_col != term->search.match.col) - { - int selection_row = start_row - term->grid->view; - while (selection_row < 0) - selection_row += term->grid->num_rows; - - assert(selection_row >= 0 && - selection_row < term->grid->num_rows); - selection_start(term, start_col, selection_row, SELECTION_NORMAL); - } - - /* Update selection endpoint */ - { - int selection_row = end_row - term->grid->view; - while (selection_row < 0) - selection_row += term->grid->num_rows; - - assert(selection_row >= 0 && - selection_row < term->grid->num_rows); - selection_update(term, end_col, selection_row); - } } static void @@ -184,7 +198,7 @@ search_find_next(struct terminal *term) int start_row = term->search.match.row; int start_col = term->search.match.col; - size_t len __attribute__((unused)) = term->search.match_len; + size_t len = term->search.match_len; assert((len == 0 && start_row == -1 && start_col == -1) || (len > 0 && start_row >= 0 && start_col >= 0)); From c50a4428103b5fd5c0ce204d850ec343cdab5fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 24 Jul 2020 17:50:48 +0200 Subject: [PATCH 05/24] readme: add section describing how to identify foot --- CHANGELOG.md | 5 +++++ README.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc70f92..ea392a60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ ## Unreleased ### Added + +* Section to [README.md](README.md) describing how to programmatically + identify foot. + + ### Changed * Primary DA to no longer indicate support for _Selective Erase_, diff --git a/README.md b/README.md index 7aa29df4..de0f5b7a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The fast, lightweight and minimalistic Wayland terminal emulator. 1. [Backspace](#backspace) 1. [DPI and font size](#dpi-and-font-size) 1. [Supported OSCs](#supported-oscs) +1. [Programmatically checking if running in foot](#programmatically-checking-if-running-in-foot) 1. [Requirements](#requirements) 1. [Running](#running) 1. [Building](#building) @@ -301,6 +302,39 @@ with the terminal emulator itself. Foot implements the following OSCs: * `OSC 555` - flash screen (**foot specific**) +## Programmatically checking if running in foot + +Foot does **not** set any environment variables that can be used to +identify foot (reading `TERM` is not reliable since the user may have +chosen to use a different terminfo). + +You can instead use the escape sequences to read the _Secondary_ and +_Tertiary Device Attributes_ (secondary/tertiary DA, for short). + +The tertiary DA response is always `\EP!|464f4f54\E\\`. The `\EP!|` is +the standard tertiary DA response prefix, `DCS ! |`. The trailing +`\E\\` is of course the standard string terminator, `ST`. + +In the response above, the interresting part is `464f4f54`; this is +the string _FOOT_ in hex. + +The secondary DA response is `\E[>1;XXYYZZ;0c`, where XXYYZZ is foot's +major, minor and patch version numbers, in decimal, using two digits +for each number. For example, foot-1.4.2 would respond with +`\E[>1;010402;0c`. + +**Note**: not all terminal emulators implement tertiary DA. Most +implement secondary DA, but not all. All _should_ however implement +_Primary DA_. + +Thus, a safe way to query the terminal is to request the tertiary, +secondary and primary DA all at once, in that order. All terminals +should ignore escape sequences they do not recognize. You will have to +parse the response (which in foot will consist of all three DA +responses, all at once) to determine which requests the terminal +emulator actually responded to. + + ## Requirements ### Running From 3d15913d386975537c2d375c33eed8cf238d52cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 08:50:57 +0200 Subject: [PATCH 06/24] license: fix bad copy-paste: first commit was in 2019 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 6d93abca..a915c5b5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Daniel Eklöf +Copyright (c) 2019 Daniel Eklöf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 373745c597f3bb1c4185668c516ccc46b86443cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 09:05:11 +0200 Subject: [PATCH 07/24] meson: install LICENSE, README.md and CHANGELOG.md --- CHANGELOG.md | 3 +++ meson.build | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea392a60..a6c93071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ * Section to [README.md](README.md) describing how to programmatically identify foot. +* [LICENSE](LICENSE), [README.md](README.md) and + [CHANGELOG.md](CHANGELOG.md) are now installed to + `${datadir}/doc/foot`. ### Changed diff --git a/meson.build b/meson.build index 0977e3c5..493b4392 100644 --- a/meson.build +++ b/meson.build @@ -148,7 +148,12 @@ custom_target( install: true, install_dir: join_paths(get_option('datadir'), 'terminfo')) -install_data('foot.desktop', 'foot-server.desktop', install_dir: join_paths(get_option('datadir'), 'applications')) +install_data( + 'LICENSE', 'README.md', 'CHANGELOG.md', + install_dir: join_paths(get_option('datadir'), 'doc', 'foot')) +install_data( + 'foot.desktop', 'foot-server.desktop', + install_dir: join_paths(get_option('datadir'), 'applications')) install_data('footrc', install_dir: join_paths(get_option('datadir'), 'foot')) subdir('completions') From 700edff2141bf02d88b1edf61edfb4dcbe2004fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 09:06:04 +0200 Subject: [PATCH 08/24] pkgbuild: include changelog --- PKGBUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/PKGBUILD b/PKGBUILD index 33cc9786..ae70f263 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -42,6 +42,7 @@ check() { package_foot-git() { pkgdesc="A wayland native terminal emulator" + changelog=CHANGELOG.md optdepends=('foot-terminfo: terminfo for foot') conflicts=('foot') provides=('foot') From bc3b4647456fe2f70a1e5139eb15432eedafc252 Mon Sep 17 00:00:00 2001 From: birger Date: Sat, 25 Jul 2020 09:39:03 +0200 Subject: [PATCH 09/24] Fix typos --- doc/foot.1.scd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 1874c0cb..8424b26a 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -214,14 +214,14 @@ _Examples_: By default, foot prefixes meta characters with *ESC*. This corresponds to XTerm's *metaSendsEscape* option set to *true*. -This can be disabled programatically with *\E[?1036l* (and enabled +This can be disabled programmatically with *\E[?1036l* (and enabled again with *\E[?1036h*). When disabled, foot will instead set the 8:th bit of meta character and then UTF-8 encode it. This corresponds to XTerm's *eightBitMeta* option set to *true*. -This can also be disabled programatically with *rmm* (Reset Meta Mode, +This can also be disabled programmatically with *rmm* (Reset Meta Mode, *\E[?1034l*), and enabled again with *smm* (Set Meta Mode, *\E[?1034h*). From 3f993d00b74877f68ce0cc424c26e2cf06f207a9 Mon Sep 17 00:00:00 2001 From: birger Date: Sat, 25 Jul 2020 09:41:50 +0200 Subject: [PATCH 10/24] Fix typo --- doc/foot.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 92ac7c01..7c3ab283 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -335,7 +335,7 @@ any of these options. Now, that was a lof of text. But what is it foot actually does? When receiving client data, it schedules a timer, the - *delayed-render-lower*. If we do not recieve any more client data + *delayed-render-lower*. If we do not receive any more client data before the timer has run out, we render the frame. If however, we do receive more data, the timer is re-scheduled. That is, each time we receive client data, frame rendering is delayed another From 057ff3ba2104b0d4058a389bcef42abd013eec2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 09:52:30 +0200 Subject: [PATCH 11/24] readme: spelling fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de0f5b7a..2e1e88b8 100644 --- a/README.md +++ b/README.md @@ -223,14 +223,14 @@ want to launch a new terminal. By default, foot prefixes _Meta characters_ with ESC. This corresponds to XTerm's `metaSendsEscape` option set to `true`. -This can be disabled programatically with `\E[?1036l` (and enabled +This can be disabled programmatically with `\E[?1036l` (and enabled again with `\E[?1036h`). When disabled, foot will instead set the 8:th bit of meta character and then UTF-8 encode it. This corresponds to XTerm's `eightBitMeta` option set to `true`. -This can also be disabled programatically with `rmm` (_reset meta +This can also be disabled programmatically with `rmm` (_reset meta mode_, `\E[?1034l`), and enabled again with `smm` (_set meta mode_, `\E[?1034h`). From 9f82cbaa496f3c9c8210d3e78bee0de038d232e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 11:23:54 +0200 Subject: [PATCH 12/24] search: fix crash when searching the scrollback history search_update_selection() was changed in 1.4.x to *first* update the selection, *then* move the viewport. This leads to a crash if the new match (selection) is outside the current viewport; the selection code assumes the updated selection endpoint is in the visible viewport. Changing back to *first* move the viewport, *then* update the selection solves this. --- CHANGELOG.md | 4 +++ search.c | 100 ++++++++++++++++++++++++++------------------------- 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c93071..171765d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,10 @@ ### Deprecated ### Removed ### Fixed + +* Crash in scrollback search + + ### Security diff --git a/search.c b/search.c index e02aaa7c..a0b87a13 100644 --- a/search.c +++ b/search.c @@ -104,6 +104,58 @@ search_update_selection(struct terminal *term, int start_row, int start_col, int end_row, int end_col) { + bool move_viewport = true; + + int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1); + if (view_end >= term->grid->view) { + /* Viewport does *not* wrap around */ + if (start_row >= term->grid->view && end_row <= view_end) + move_viewport = false; + } else { + /* Viewport wraps */ + if (start_row >= term->grid->view || end_row <= view_end) + move_viewport = false; + } + + if (move_viewport) { + int old_view = term->grid->view; + int new_view = start_row - term->rows / 2; + + while (new_view < 0) + new_view += term->grid->num_rows; + + /* Prevent scrolling in uninitialized rows */ + bool all_initialized = false; + do { + all_initialized = true; + + for (int i = 0; i < term->rows; i++) { + int row_no = (new_view + i) % term->grid->num_rows; + if (term->grid->rows[row_no] == NULL) { + all_initialized = false; + new_view--; + break; + } + } + } while (!all_initialized); + + /* Don't scroll past scrollback history */ + int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; + if (end >= term->grid->offset) { + /* Not wrapped */ + if (new_view >= term->grid->offset && new_view <= end) + new_view = term->grid->offset; + } else { + if (new_view >= term->grid->offset || new_view <= end) + new_view = term->grid->offset; + } + + /* Update view */ + term->grid->view = new_view; + if (new_view != old_view) + term_damage_view(term); + } + /* Selection endpoint is inclusive */ if (--end_col < 0) { end_col = term->cols - 1; @@ -133,54 +185,6 @@ search_update_selection(struct terminal *term, selection_row < term->grid->num_rows); selection_update(term, end_col, selection_row); } - - int view_end = (term->grid->view + term->rows - 1) & (term->grid->num_rows - 1); - if (view_end >= term->grid->view) { - /* Viewport does *not* wrap around */ - if (start_row >= term->grid->view && end_row <= view_end) - return; - } else { - /* Viewport wraps */ - if (start_row >= term->grid->view || end_row <= view_end) - return; - } - - int old_view = term->grid->view; - int new_view = start_row - term->rows / 2; - - while (new_view < 0) - new_view += term->grid->num_rows; - - /* Prevent scrolling in uninitialized rows */ - bool all_initialized = false; - do { - all_initialized = true; - - for (int i = 0; i < term->rows; i++) { - int row_no = (new_view + i) % term->grid->num_rows; - if (term->grid->rows[row_no] == NULL) { - all_initialized = false; - new_view--; - break; - } - } - } while (!all_initialized); - - /* Don't scroll past scrollback history */ - int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; - if (end >= term->grid->offset) { - /* Not wrapped */ - if (new_view >= term->grid->offset && new_view <= end) - new_view = term->grid->offset; - } else { - if (new_view >= term->grid->offset || new_view <= end) - new_view = term->grid->offset; - } - - /* Update view */ - term->grid->view = new_view; - if (new_view != old_view) - term_damage_view(term); } static void From b5668a72d345b74ec8145004b081f2f67b612d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=27cherti=27=20Gro=C3=9Fe=20Sundrup?= Date: Sat, 25 Jul 2020 13:30:43 +0200 Subject: [PATCH 13/24] Correct the location of footrc in manpage --- doc/foot.1.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 8424b26a..883ae8b1 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -13,7 +13,7 @@ arguments, to execute (instead of the default shell). # OPTIONS *-c*,*--config*=_PATH_ - Path to configuration file. Default: *XDG_RUNTIME_DIR/footrc*. + Path to configuration file. Default: *XDG_CONFIG_HOME/footrc*. *-f*,*--font*=_FONT_ Comma separated list of fonts to use, in fontconfig format (see From 38ba3f5429af2966a1448e41f90f0b259abe0adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=27cherti=27=20Gro=C3=9Fe=20Sundrup?= Date: Sat, 25 Jul 2020 13:18:12 +0200 Subject: [PATCH 14/24] Add configuration instructions to the README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e1e88b8..233703d1 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ The fast, lightweight and minimalistic Wayland terminal emulator. ## Index 1. [Features](#features) +1. [Configuration](#configuration) 1. [Troubleshooting](#troubleshooting) 1. [Why the name 'foot'?](#why-the-name-foot) 1. [Fonts](#fonts) @@ -34,7 +35,6 @@ The fast, lightweight and minimalistic Wayland terminal emulator. 1. [Bugs](#bugs) 1. [Mastodon](#mastodon) - ## Features * Fast (see [benchmarks](doc/benchmark.md)) @@ -53,6 +53,14 @@ The fast, lightweight and minimalistic Wayland terminal emulator. ![wow](doc/sixel-wow.png "Sixel screenshot") +## Configuration + +**foot** can be configured by creating a file `$XDG_CONFIG_HOME/footrc` (defaulting to `~/.config/footrc`). +A template for that can usually be found in `/usr/share/foot/footrc` or +[here](https://codeberg.org/dnkl/foot/src/branch/master/footrc). + +Further information can be found in foot's manpage `foot(5)`. + ## Troubleshooting From ed945611a6e555a2dca2ccb9b3df0752f469ded1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=27cherti=27=20Gro=C3=9Fe=20Sundrup?= Date: Sat, 25 Jul 2020 13:21:27 +0200 Subject: [PATCH 15/24] Add inline color-number-mapping as comment --- footrc | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/footrc b/footrc index 624c688b..e7139a83 100644 --- a/footrc +++ b/footrc @@ -19,22 +19,22 @@ # alpha=1.0 # foreground=dcdccc # background=111111 -# regular0=222222 -# regular1=cc9393 -# regular2=7f9f7f -# regular3=d0bf8f -# regular4=6ca0a3 -# regular5=dc8cc3 -# regular6=93e0e3 -# regular7=dcdccc -# bright0=666666 -# bright1=dca3a3 -# bright2=bfebbf -# bright3=f0dfaf -# bright4=8cd0d3 -# bright5=fcace3 -# bright6=b3ffff -# bright7=ffffff +# regular0=222222 # black +# regular1=cc9393 # red +# regular2=7f9f7f # green +# regular3=d0bf8f # yellow +# regular4=6ca0a3 # blue +# regular5=dc8cc3 # magenta +# regular6=93e0e3 # cyan +# regular7=dcdccc # white +# bright0=666666 # bright black +# bright1=dca3a3 # bright red +# bright2=bfebbf # bright green +# bright3=f0dfaf # bright yellow +# bright4=8cd0d3 # bright blue +# bright5=fcace3 # bright magenta +# bright6=b3ffff # bright cyan +# bright7=ffffff # bright white [csd] # preferred=server From 58cec40016a68561313ecceb09df33d289c34e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 13:51:24 +0200 Subject: [PATCH 16/24] doc: benchmarks: update 'desktop' results after foot-1.4.0 release --- doc/benchmark.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/benchmark.md b/doc/benchmark.md index daac1e10..0f35f108 100644 --- a/doc/benchmark.md +++ b/doc/benchmark.md @@ -18,7 +18,7 @@ terminal. This is done **20** times for each test. Then it calculates the _mean_ and _standard deviation_ for each test. -## 2020-06-05 +## 2020-07-25 ### System @@ -40,13 +40,13 @@ Scrollback: 10000 lines ### Results -| Benchmark | Foot (GCC+PGO) 1.3.0.r59 | Alacritty 0.4.3 | URxvt 9.22 | XTerm 356 | +| Benchmark | Foot (GCC+PGO) 1.4.2.r14 | Alacritty 0.4.3 | URxvt 9.22 | XTerm 358 | |------------------------|-------------------------:|---------------------:|---------------:|---------------:| -| alt-random | 0.450s ±0.009 | 0.905s ±0.003 | 1.151s ±0.004 | 12.906s ±0.078 | -| alt-random-colors | 0.451s ±0.013 | 0.931s ±0.005 | 1.192s ±0.005 | 11.858s ±0.155 | -| scrolling | 1.181s ±0.036 | 1.096s ±0.022 | 1.080s ±0.007 | 38.244s ±0.118 | -| scrolling-filled-lines | 0.878s ±0.015 | 1.320s ±0.040 | 1.251s ±0.006 | 6.812s ±0.031 | -| unicode-random | 0.926s ±1.179 | 0.089s ±0.001 [^1] | 24.039s ±3.559 | 26.558s ±3.841 | +| alt-random | 0.423s ±0.014 | 0.904s ±0.006 | 1.111s ±0.003 | 12.851s ±0.087 | +| alt-random-colors | 0.382s ±0.005 | 0.935s ±0.005 | 1.146s ±0.007 | 11.816s ±0.088 | +| scrolling | 1.380s ±0.048 | 1.011s ±0.012 | 1.021s ±0.016 | 38.483s ±0.122 | +| scrolling-filled-lines | 0.826s ±0.020 | 1.307s ±0.008 | 1.213s ±0.015 | 6.725s ±0.016 | +| unicode-random | 0.243s ±0.006 | 0.091s ±0.003 [^1] | 24.507s ±3.264 | 26.127s ±3.891 | From 4153d77febfc09a618b78dcd22678ca966d1e2ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 13:55:05 +0200 Subject: [PATCH 17/24] changelog: add 'contributors' section --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 171765d0..df304262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,10 @@ ### Security +### Contributors + +* [birger](https://codeberg.org/birger) +* [cherti](https://codeberg.org/cherti) ## 1.4.2 From 80741371c9074d227f523ef462af778745ab91bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 25 Jul 2020 14:20:33 +0200 Subject: [PATCH 18/24] doc: benchmark: update 'laptop' results after foot-1.4.0 --- doc/benchmark.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/benchmark.md b/doc/benchmark.md index 0f35f108..8d4bb1fe 100644 --- a/doc/benchmark.md +++ b/doc/benchmark.md @@ -50,7 +50,7 @@ Scrollback: 10000 lines -## 2020-05-31 +## 2020-07-25 ### System @@ -73,13 +73,13 @@ Scrollback=10000 lines ### Results -| Benchmark | Foot (GCC+PGO) 1.3.0.r59 | Alacritty 0.4.2 | URxvt 9.22 | St 0.8.3 | XTerm 356 | -|------------------------|-------------------------:|---------------------:|---------------:|--------------:|---------------:| -| alt-random | 0.791s ±0.080 | 1.558s ±0.038 | 1.746s ±0.065 | 2.628s ±0.085 | 1.706s ±0.064 | -| alt-random-colors | 0.830s ±0.076 | 1.587s ±0.041 | 2.049s ±0.118 | 3.033s ±0.129 | 2.109s ±0.131 | -| scrolling | 1.603s ±0.070 | 1.464s ±0.098 | 1.439s ±0.035 | 3.760s ±0.113 | 1.459s ±0.036 | -| scrolling-filled-lines | 1.888s ±0.021 | 2.334s ±0.078 | 2.145s ±0.074 | 3.372s ±0.078 | 2.144s ±0.091 | -| unicode-random | 1.545s ±0.229 | 0.164s ±0.012 [^1] | 11.180s ±0.342 | crashed | 11.389s ±0.269 | +| Benchmark | Foot (GCC+PGO) 1.4.2.r9 | Alacritty 0.4.3 | URxvt 9.22 | St 0.8.4 | XTerm 358 | +|------------------------|------------------------:|---------------------:|---------------:|--------------:|----------------:| +| alt-random | 0.784s ±0.074 | 1.568s ±0.094 | 1.600s ±0.052 | 1.917s ±0.054 | 34.487s ±0.118 | +| alt-random-colors | 0.823s ±0.067 | 1.627s ±0.107 | 1.932s ±0.073 | 2.111s ±0.163 | 30.676s ±0.127 | +| scrolling | 1.612s ±0.092 | 1.492s ±0.051 | 1.504s ±0.033 | 3.767s ±0.140 | 125.202s ±0.383 | +| scrolling-filled-lines | 1.874s ±0.039 | 2.423s ±0.083 | 1.994s ±0.037 | 2.751s ±0.076 | 19.608s ±0.056 | +| unicode-random | 0.458s ±0.026 | 0.159s ±0.007 [^1] | 12.416s ±0.223 | crashed | 16.336s ±0.410 | [^1]: [Alacritty and "unicode-random"](#alacritty-and-unicode-random) From 22cd25d36059c784ea0da3ebeed063414aad44d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 06:03:30 +0200 Subject: [PATCH 19/24] tokenize: reset *argv = NULL on error This allows the caller to call free() without having to worry about whether it has already been free:d or not. Closes #49. --- tokenize.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tokenize.c b/tokenize.c index b4aab6b5..703ecb07 100644 --- a/tokenize.c +++ b/tokenize.c @@ -46,6 +46,7 @@ tokenize_cmdline(char *cmdline, char ***argv) if (delim != ' ') { LOG_ERR("unterminated %s quote\n", delim == '"' ? "double" : "single"); free(*argv); + *argv = NULL; return false; } From a9eeeedc90224cb74b6d265c91c1a60fa884254c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 06:04:29 +0200 Subject: [PATCH 20/24] tokenize: remove newline from log message (LOG_ERR appends one for us) --- tokenize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokenize.c b/tokenize.c index 703ecb07..2671e23b 100644 --- a/tokenize.c +++ b/tokenize.c @@ -44,7 +44,7 @@ tokenize_cmdline(char *cmdline, char ***argv) char *end = strchr(p, delim); if (end == NULL) { if (delim != ' ') { - LOG_ERR("unterminated %s quote\n", delim == '"' ? "double" : "single"); + LOG_ERR("unterminated %s quote", delim == '"' ? "double" : "single"); free(*argv); *argv = NULL; return false; From faad0936270171467546c920e8cb629c0aa69efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:41:35 +0200 Subject: [PATCH 21/24] changelog: mention fix for crash on unclosed quote in tokenizer --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df304262..d4836891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ ### Fixed * Crash in scrollback search +* Crash when a **pipe-visible** or **pipe-scrollback** command + contained an unclosed quote + (https://codeberg.org/dnkl/foot/issues/49). ### Security From 50bd51c4d43931418c5b8c706841b46b67c1a947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:43:41 +0200 Subject: [PATCH 22/24] tokenize: handle escaped quotes We only support escaping quotes inside a quote, and only of the same type as the enclosing quote. I.e. "double quote \"escaped double quote\"" But not "double quote \'invalid escaped single quote\'" --- CHANGELOG.md | 2 ++ tokenize.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4836891..764e8f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ * [LICENSE](LICENSE), [README.md](README.md) and [CHANGELOG.md](CHANGELOG.md) are now installed to `${datadir}/doc/foot`. +* Support for escaping quotes in **pipe-visible** and + **pipe-scrollback** commands. ### Changed diff --git a/tokenize.c b/tokenize.c index 2671e23b..35d52345 100644 --- a/tokenize.c +++ b/tokenize.c @@ -38,10 +38,11 @@ tokenize_cmdline(char *cmdline, char ***argv) char delim = first_token_is_quoted ? cmdline[0] : ' '; char *p = first_token_is_quoted ? &cmdline[1] : &cmdline[0]; + char *search_start = p; size_t idx = 0; while (*p != '\0') { - char *end = strchr(p, delim); + char *end = strchr(search_start, delim); if (end == NULL) { if (delim != ' ') { LOG_ERR("unterminated %s quote", delim == '"' ? "double" : "single"); @@ -58,6 +59,15 @@ tokenize_cmdline(char *cmdline, char ***argv) return true; } + if (end > p && *(end - 1) == '\\') { + /* Escaped quote, remove one level of escaping and + * continue searching for "our" closing quote */ + memmove(end - 1, end, strlen(end)); + end[strlen(end) - 1] = '\0'; + search_start = end; + continue; + } + *end = '\0'; if (!push_argv(argv, &argv_size, p, &idx)) @@ -75,6 +85,7 @@ tokenize_cmdline(char *cmdline, char ***argv) p++; } else delim = ' '; + search_start = p; } if (!push_argv(argv, &argv_size, NULL, &idx)) From 7127a0a6c393ee888a7b640c5481e191e0744519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:44:41 +0200 Subject: [PATCH 23/24] selection: extending a selection is now interactive That is, a selection extension can be resized just like an ordinary extension. --- CHANGELOG.md | 4 +++- input.c | 2 +- selection.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 764e8f46..53c2462a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,13 +37,15 @@ outside it. * Scrollback search to focus match, that requires a viewport change, roughly in the center of the screen. +* Extending a selection with the right mouse button now works while + dragging the mouse. ### Deprecated ### Removed ### Fixed -* Crash in scrollback search +* Crash in scrollback search. * Crash when a **pipe-visible** or **pipe-scrollback** command contained an unclosed quote (https://codeberg.org/dnkl/foot/issues/49). diff --git a/input.c b/input.c index 442cd322..c7f4b073 100644 --- a/input.c +++ b/input.c @@ -1171,7 +1171,7 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) return; - bool update_selection = seat->mouse.button == BTN_LEFT; + bool update_selection = seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) diff --git a/selection.c b/selection.c index d5add464..354f6f53 100644 --- a/selection.c +++ b/selection.c @@ -372,8 +372,8 @@ selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial if (row < start->row || (row == start->row && col < start->col)) { /* Extend selection to start *before* current start */ - new_start = (struct coord){col, row}; - new_end = *end; + new_start = *end; + new_end = (struct coord){col, row}; } else if (row > end->row || (row == end->row && col > end->col)) { @@ -391,8 +391,8 @@ selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial abs(linear - (end->row * term->cols + end->col))) { /* Move start point */ - new_start = (struct coord){col, row}; - new_end = *end; + new_start = *end; + new_end = (struct coord){col, row}; } else { @@ -440,13 +440,13 @@ selection_extend_block(struct terminal *term, int col, int row, uint32_t serial) /* Move one of the top corners */ if (abs(col - top_left.col) < abs(col - top_right.col)) { - new_start = (struct coord){col, row}; - new_end = bottom_right; + new_start = bottom_right; + new_end = (struct coord){col, row}; } else { - new_start = (struct coord){col, row}; - new_end = bottom_left; + new_start = bottom_left; + new_end = (struct coord){col, row}; } } From 77afd615251ebff7b090454c180a5f5470cb97e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 27 Jul 2020 16:45:34 +0200 Subject: [PATCH 24/24] doc: foot.5: modifiers+keys are plural --- doc/foot.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 7c3ab283..d837cd1a 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -176,7 +176,7 @@ This section lets you override the default key bindings. The general format is _action=combo1...comboN_. That is, each action may have one or more key combinations, space separated. Each combination is on the form _mod1+mod2+key_. The names of the modifiers -and the key *must* be a valid XKB key name. +and the key *must* be valid XKB key names. Note that if *Shift* is one of the modifiers, the _key_ *must* be in upper case. For example, *Control+Shift+v* will never trigger -