Skip to content

Commit 03c7113

Browse files
committed
[prompt] support cmd-c/cmd-a for copy/select-all
1 parent ee34494 commit 03c7113

9 files changed

Lines changed: 126 additions & 68 deletions

NEWS.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11

2+
## lnav v0.14.1
3+
4+
Features:
5+
* For terminals that support the Kitty Keyboard
6+
protocol, add support for:
7+
- ⌘-C to copy the current line to the clipboard
8+
- ⌘-A to select all text in the prompt.
9+
* The `measure_with_units` collator now recognizes
10+
(KiB, MiB, ...).
11+
12+
Breaking changes:
13+
* The `humanize_file_size()` SQLite function now
14+
uses 1,000 for the base instead of 1,024.
15+
16+
Bug Fixes:
17+
* Fix a bug in file loading that could cause a short
18+
read and crash in some situations.
19+
20+
221
## lnav v0.14.0
322

423
Features:

docs/schemas/config-v1.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@
11001100
"title": "/ui/keymap-defs/<keymap_name>",
11011101
"type": "object",
11021102
"patternProperties": {
1103-
"^((?:x[0-9a-f]{2}|f[0-9]{1,2})+)$": {
1103+
"^((?:(?:cmd-)?x[0-9a-f]{2}|f[0-9]{1,2})+)$": {
11041104
"description": "Map of key codes to commands to execute. The field names are the keys to be mapped using as a hexadecimal representation of the UTF-8 encoding. Each byte of the UTF-8 should start with an 'x' followed by the hexadecimal representation of the byte.",
11051105
"title": "/ui/keymap-defs/<keymap_name>/<key_seq>",
11061106
"type": "object",

src/input_dispatcher.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ using namespace ww898;
4747

4848
template<typename A>
4949
static void
50-
to_key_seq(A& dst, uint32_t* src)
50+
to_key_seq(A& dst, ncinput& ch)
5151
{
5252
dst[0] = '\0';
53-
for (size_t lpc = 0; src[lpc]; lpc++) {
54-
ww898::utf::utf8::write(src[lpc], [&dst](uint8_t ch) {
53+
if (ncinput_super_p(&ch)) {
54+
strcpy(&dst[0], "cmd-");
55+
}
56+
for (size_t lpc = 0; ch.eff_text[lpc]; lpc++) {
57+
ww898::utf::utf8::write(ch.eff_text[lpc], [&dst](uint8_t ch) {
5558
snprintf(dst.data() + strlen(dst.data()),
5659
dst.size() - strlen(dst.data()),
5760
"x%02x",
@@ -61,7 +64,7 @@ to_key_seq(A& dst, uint32_t* src)
6164
}
6265

6366
void
64-
input_dispatcher::new_input(const struct timeval& current_time,
67+
input_dispatcher::new_input(const timeval& current_time,
6568
notcurses* nc,
6669
ncinput& ch)
6770
{
@@ -113,7 +116,7 @@ input_dispatcher::new_input(const struct timeval& current_time,
113116
log_debug("nckey %s", keyseq.data());
114117
handled = this->id_key_handler(nc, ch, keyseq.data());
115118
} else {
116-
to_key_seq(keyseq, ch.eff_text);
119+
to_key_seq(keyseq, ch);
117120
handled = this->id_key_handler(nc, ch, keyseq.data());
118121
}
119122

src/keymaps/default-keymap.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@
133133
"command": ":next-mark warning",
134134
"alt-msg": "${keymap_def_alt_hour_boundary}"
135135
},
136+
"cmd-x63": {
137+
"command": "|lnav-copy-text",
138+
"alt-msg": "${keymap_def_clear}"
139+
},
136140
"x63": {
137141
"command": "|lnav-copy-text",
138142
"alt-msg": "${keymap_def_clear}"

src/lnav_config.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ static const struct json_path_container key_command_handlers = {
543543

544544
static const struct json_path_container keymap_def_handlers = {
545545
yajlpp::pattern_property_handler(
546-
"(?<key_seq>(?:x[0-9a-f]{2}|f[0-9]{1,2})+)")
546+
"(?<key_seq>(?:(?:cmd-)?x[0-9a-f]{2}|f[0-9]{1,2})+)")
547547
.with_synopsis("<utf8-key-code-in-hex>")
548548
.with_description(
549549
"Map of key codes to commands to execute. The field names are "

src/textinput_curses.cc

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -386,36 +386,7 @@ textinput_curses::handle_mouse(mouse_event& me)
386386
this->set_needs_update();
387387
}
388388
} else if (me.me_button == mouse_button_t::BUTTON_RIGHT) {
389-
if (this->tc_selection) {
390-
std::string content;
391-
auto range = this->tc_selection;
392-
auto add_nl = false;
393-
for (auto y = range->sr_start.y;
394-
y <= range->sr_end.y && y < this->tc_lines.size();
395-
++y)
396-
{
397-
if (add_nl) {
398-
content.push_back('\n');
399-
}
400-
auto sel_range = range->range_for_line(y);
401-
if (!sel_range) {
402-
continue;
403-
}
404-
405-
const auto& al = this->tc_lines[y];
406-
auto byte_start = al.column_to_byte_index(sel_range->lr_start);
407-
auto byte_end = al.column_to_byte_index(sel_range->lr_end);
408-
auto al_sf = string_fragment::from_str_range(
409-
al.al_string, byte_start, byte_end);
410-
content += al_sf;
411-
add_nl = true;
412-
}
413-
414-
this->tc_clipboard.clear();
415-
this->tc_cut_location = this->tc_cursor;
416-
this->tc_clipboard.emplace_back(content);
417-
this->sync_to_sysclip();
418-
}
389+
this->copy_selection();
419390
} else if (me.me_button == mouse_button_t::BUTTON_LEFT) {
420391
this->tc_mode = mode_t::editing;
421392
auto adj_press_x = me.me_press_x;
@@ -907,6 +878,23 @@ textinput_curses::handle_key(const ncinput& ch)
907878
return true;
908879
}
909880

881+
if (ncinput_super_p(&ch)) {
882+
switch (chid) {
883+
case 'a': {
884+
this->tc_selection
885+
= this->clamp_selection(selected_range::from_mouse(
886+
input_point::home(), input_point::end()));
887+
this->set_needs_update();
888+
break;
889+
}
890+
case 'c': {
891+
this->copy_selection();
892+
break;
893+
}
894+
}
895+
return true;
896+
}
897+
910898
if (ncinput_alt_p(&ch)) {
911899
switch (chid) {
912900
case NCKEY_LEFT: {
@@ -2403,3 +2391,38 @@ textinput_curses::add_mark(input_point pos,
24032391

24042392
this->tc_marks.emplace(pos, msg);
24052393
}
2394+
2395+
void
2396+
textinput_curses::copy_selection()
2397+
{
2398+
if (this->tc_selection) {
2399+
std::string content;
2400+
auto range = this->tc_selection;
2401+
auto add_nl = false;
2402+
for (auto y = range->sr_start.y;
2403+
y <= range->sr_end.y && y < this->tc_lines.size();
2404+
++y)
2405+
{
2406+
if (add_nl) {
2407+
content.push_back('\n');
2408+
}
2409+
auto sel_range = range->range_for_line(y);
2410+
if (!sel_range) {
2411+
continue;
2412+
}
2413+
2414+
const auto& al = this->tc_lines[y];
2415+
auto byte_start = al.column_to_byte_index(sel_range->lr_start);
2416+
auto byte_end = al.column_to_byte_index(sel_range->lr_end);
2417+
auto al_sf = string_fragment::from_str_range(
2418+
al.al_string, byte_start, byte_end);
2419+
content += al_sf;
2420+
add_nl = true;
2421+
}
2422+
2423+
this->tc_clipboard.clear();
2424+
this->tc_cut_location = this->tc_cursor;
2425+
this->tc_clipboard.emplace_back(content);
2426+
this->sync_to_sysclip();
2427+
}
2428+
}

src/textinput_curses.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ public:
436436

437437
void add_mark(input_point pos, const lnav::console::user_message& msg);
438438

439+
void copy_selection();
440+
439441
void sync_to_sysclip() const;
440442

441443
enum class mode_t {

test/expected/test_cli.sh_0b3639753916f71254e8c9cce4ebb8bfd9978d3e.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9101,6 +9101,11 @@
91019101
}
91029102
},
91039103
"default": {
9104+
"cmd-x63": {
9105+
"id": "",
9106+
"command": "|lnav-copy-text",
9107+
"alt-msg": "${keymap_def_clear}"
9108+
},
91049109
"f1": {
91059110
"id": "",
91069111
"command": ":help",

test/expected/test_cli.sh_cc06341dd560f927512e92c7c0985ed8b25827ae.out

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@
111111
/ui/keymap-defs/de/x37/command -> de-keymap.json:25
112112
/ui/keymap-defs/de/x38/command -> de-keymap.json:28
113113
/ui/keymap-defs/de/xc2xa7/command -> de-keymap.json:37
114+
/ui/keymap-defs/default/cmd-x63/alt-msg -> default-keymap.json:138
115+
/ui/keymap-defs/default/cmd-x63/command -> default-keymap.json:137
114116
/ui/keymap-defs/default/f1/command -> default-keymap.json:24
115117
/ui/keymap-defs/default/f7/command -> default-keymap.json:27
116118
/ui/keymap-defs/default/f8/command -> default-keymap.json:30
@@ -119,11 +121,11 @@
119121
/ui/keymap-defs/default/x04/command -> default-keymap.json:97
120122
/ui/keymap-defs/default/x06/command -> default-keymap.json:85
121123
/ui/keymap-defs/default/x0c/command -> default-keymap.json:88
122-
/ui/keymap-defs/default/x0f/command -> default-keymap.json:173
124+
/ui/keymap-defs/default/x0f/command -> default-keymap.json:177
123125
/ui/keymap-defs/default/x12/command -> default-keymap.json:91
124126
/ui/keymap-defs/default/x13/command -> default-keymap.json:37
125127
/ui/keymap-defs/default/x15/command -> default-keymap.json:100
126-
/ui/keymap-defs/default/x17/command -> default-keymap.json:163
128+
/ui/keymap-defs/default/x17/command -> default-keymap.json:167
127129
/ui/keymap-defs/default/x18/command -> default-keymap.json:94
128130
/ui/keymap-defs/default/x21/command -> default-keymap.json:64
129131
/ui/keymap-defs/default/x23/command -> default-keymap.json:70
@@ -141,48 +143,48 @@
141143
/ui/keymap-defs/default/x3a/command -> default-keymap.json:109
142144
/ui/keymap-defs/default/x3b/command -> default-keymap.json:118
143145
/ui/keymap-defs/default/x3d/command -> default-keymap.json:103
144-
/ui/keymap-defs/default/x3f/command -> default-keymap.json:184
146+
/ui/keymap-defs/default/x3f/command -> default-keymap.json:188
145147
/ui/keymap-defs/default/x40/command -> default-keymap.json:67
146148
/ui/keymap-defs/default/x42/command -> default-keymap.json:82
147149
/ui/keymap-defs/default/x45/alt-msg -> default-keymap.json:122
148150
/ui/keymap-defs/default/x45/command -> default-keymap.json:121
149-
/ui/keymap-defs/default/x4e/alt-msg -> default-keymap.json:146
150-
/ui/keymap-defs/default/x4e/command -> default-keymap.json:145
151-
/ui/keymap-defs/default/x50/alt-msg -> default-keymap.json:192
152-
/ui/keymap-defs/default/x50/command -> default-keymap.json:191
153-
/ui/keymap-defs/default/x51/command -> default-keymap.json:205
154-
/ui/keymap-defs/default/x54/alt-msg -> default-keymap.json:154
155-
/ui/keymap-defs/default/x54/command -> default-keymap.json:153
156-
/ui/keymap-defs/default/x55/command -> default-keymap.json:170
151+
/ui/keymap-defs/default/x4e/alt-msg -> default-keymap.json:150
152+
/ui/keymap-defs/default/x4e/command -> default-keymap.json:149
153+
/ui/keymap-defs/default/x50/alt-msg -> default-keymap.json:196
154+
/ui/keymap-defs/default/x50/command -> default-keymap.json:195
155+
/ui/keymap-defs/default/x51/command -> default-keymap.json:209
156+
/ui/keymap-defs/default/x54/alt-msg -> default-keymap.json:158
157+
/ui/keymap-defs/default/x54/command -> default-keymap.json:157
158+
/ui/keymap-defs/default/x55/command -> default-keymap.json:174
157159
/ui/keymap-defs/default/x57/alt-msg -> default-keymap.json:130
158160
/ui/keymap-defs/default/x57/command -> default-keymap.json:129
159161
/ui/keymap-defs/default/x58/command -> default-keymap.json:106
160162
/ui/keymap-defs/default/x5e/command -> default-keymap.json:79
161-
/ui/keymap-defs/default/x60/command -> default-keymap.json:196
162-
/ui/keymap-defs/default/x60/id -> default-keymap.json:195
163-
/ui/keymap-defs/default/x63/alt-msg -> default-keymap.json:138
164-
/ui/keymap-defs/default/x63/command -> default-keymap.json:137
163+
/ui/keymap-defs/default/x60/command -> default-keymap.json:200
164+
/ui/keymap-defs/default/x60/id -> default-keymap.json:199
165+
/ui/keymap-defs/default/x63/alt-msg -> default-keymap.json:142
166+
/ui/keymap-defs/default/x63/command -> default-keymap.json:141
165167
/ui/keymap-defs/default/x65/alt-msg -> default-keymap.json:126
166168
/ui/keymap-defs/default/x65/command -> default-keymap.json:125
167-
/ui/keymap-defs/default/x69/alt-msg -> default-keymap.json:188
168-
/ui/keymap-defs/default/x69/command -> default-keymap.json:187
169-
/ui/keymap-defs/default/x6d/alt-msg -> default-keymap.json:142
170-
/ui/keymap-defs/default/x6d/command -> default-keymap.json:141
171-
/ui/keymap-defs/default/x6e/alt-msg -> default-keymap.json:150
172-
/ui/keymap-defs/default/x6e/command -> default-keymap.json:149
173-
/ui/keymap-defs/default/x70/command -> default-keymap.json:157
174-
/ui/keymap-defs/default/x71/command -> default-keymap.json:202
175-
/ui/keymap-defs/default/x75/alt-msg -> default-keymap.json:167
176-
/ui/keymap-defs/default/x75/command -> default-keymap.json:166
177-
/ui/keymap-defs/default/x76/command -> default-keymap.json:199
169+
/ui/keymap-defs/default/x69/alt-msg -> default-keymap.json:192
170+
/ui/keymap-defs/default/x69/command -> default-keymap.json:191
171+
/ui/keymap-defs/default/x6d/alt-msg -> default-keymap.json:146
172+
/ui/keymap-defs/default/x6d/command -> default-keymap.json:145
173+
/ui/keymap-defs/default/x6e/alt-msg -> default-keymap.json:154
174+
/ui/keymap-defs/default/x6e/command -> default-keymap.json:153
175+
/ui/keymap-defs/default/x70/command -> default-keymap.json:161
176+
/ui/keymap-defs/default/x71/command -> default-keymap.json:206
177+
/ui/keymap-defs/default/x75/alt-msg -> default-keymap.json:171
178+
/ui/keymap-defs/default/x75/command -> default-keymap.json:170
179+
/ui/keymap-defs/default/x76/command -> default-keymap.json:203
178180
/ui/keymap-defs/default/x77/alt-msg -> default-keymap.json:134
179181
/ui/keymap-defs/default/x77/command -> default-keymap.json:133
180-
/ui/keymap-defs/default/x78/command -> default-keymap.json:160
181-
/ui/keymap-defs/default/x7b/alt-msg -> default-keymap.json:181
182-
/ui/keymap-defs/default/x7b/command -> default-keymap.json:180
182+
/ui/keymap-defs/default/x78/command -> default-keymap.json:164
183+
/ui/keymap-defs/default/x7b/alt-msg -> default-keymap.json:185
184+
/ui/keymap-defs/default/x7b/command -> default-keymap.json:184
183185
/ui/keymap-defs/default/x7c/command -> default-keymap.json:112
184-
/ui/keymap-defs/default/x7d/alt-msg -> default-keymap.json:177
185-
/ui/keymap-defs/default/x7d/command -> default-keymap.json:176
186+
/ui/keymap-defs/default/x7d/alt-msg -> default-keymap.json:181
187+
/ui/keymap-defs/default/x7d/command -> default-keymap.json:180
186188
/ui/keymap-defs/fr/x22/command -> fr-keymap.json:13
187189
/ui/keymap-defs/fr/x26/command -> fr-keymap.json:7
188190
/ui/keymap-defs/fr/x27/command -> fr-keymap.json:16

0 commit comments

Comments
 (0)