Skip to content

Commit b5887b1

Browse files
committed
Add duplicate line support
1 parent 5a4b87a commit b5887b1

File tree

12 files changed

+153
-39
lines changed

12 files changed

+153
-39
lines changed

README.md

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -173,45 +173,46 @@ The tool has built-in help that can be accessed by using the `?` key.
173173
174174
Key bindings can be customized, see [configuration](readme/customization.md#key-bindings) for all key bindings and information on configuring.
175175
176-
| Key | Mode | Description |
177-
|-------------|-------------|-------------------------------------------|
178-
| `?` | All | Show help |
179-
| Up | Normal/Diff | Move selection up |
180-
| Down | Normal/Diff | Move selection down |
181-
| Page Up | Normal/Diff | Move selection up five lines |
182-
| Page Down | Normal/Diff | Move selection down five lines |
183-
| Home | Normal/Diff | Move selection to start of list |
184-
| End | Normal/Diff | Move selection to home of list |
185-
| `q` | Normal/Diff | Abort interactive rebase |
186-
| `Q` | Normal/Diff | Immediately abort interactive rebase |
187-
| `w` | Normal/Diff | Write interactive rebase file |
188-
| `W` | Normal/Diff | Immediately write interactive rebase file |
189-
| `j` | Normal/Diff | Move selected commit(s) down |
190-
| `k` | Normal/Diff | Move selected commit(s) up |
191-
| `b` | Normal | Toggle break action |
192-
| `p` | Normal/Diff | Set selected commit(s) to be picked |
193-
| `r` | Normal/Diff | Set selected commit(s) to be reworded |
194-
| `e` | Normal/Diff | Set selected commit(s) to be edited |
195-
| `s` | Normal/Diff | Set selected commit(s) to be squashed |
196-
| `f` | Normal/Diff | Set selected commit(s) to be fixed-up |
197-
| `d` | Normal | Set selected commit(s) to be dropped |
198-
| `d` | Diff | Show full commit diff |
199-
| `E` | Normal | Edit the command of an editable action |
200-
| `v` | Normal/Diff | Enter and exit visual mode (for selection)|
201-
| `I` | Normal | Insert a new line |
202-
| `Delete` | Normal/Diff | Remove selected lines |
203-
| `!` | Normal/Diff | Open todo file in external editor |
204-
| `Control+z` | Normal/Diff | Undo the previous change |
205-
| `Control+y` | Normal/Diff | Redo the previously undone change |
206-
| `c` | Normal/Diff | Show commit information |
207-
| Down | Diff | Scroll view down |
208-
| Up | Diff | Scroll view up |
209-
| Left | Diff | Scroll view left |
210-
| Right | Diff | Scroll view right |
211-
| Home | Diff | Scroll view to the top |
212-
| End | Diff | Scroll view to the end |
213-
| PageUp | Diff | Scroll view a step up |
214-
| PageDown | Diff | Scroll view a step down |
176+
| Key | Mode | Description |
177+
|-------------|-------------|--------------------------------------------|
178+
| `?` | All | Show help |
179+
| Up | Normal/Diff | Move selection up |
180+
| Down | Normal/Diff | Move selection down |
181+
| Page Up | Normal/Diff | Move selection up five lines |
182+
| Page Down | Normal/Diff | Move selection down five lines |
183+
| Home | Normal/Diff | Move selection to start of list |
184+
| End | Normal/Diff | Move selection to home of list |
185+
| `q` | Normal/Diff | Abort interactive rebase |
186+
| `Q` | Normal/Diff | Immediately abort interactive rebase |
187+
| `w` | Normal/Diff | Write interactive rebase file |
188+
| `W` | Normal/Diff | Immediately write interactive rebase file |
189+
| `j` | Normal/Diff | Move selected commit(s) down |
190+
| `k` | Normal/Diff | Move selected commit(s) up |
191+
| `b` | Normal | Toggle break action |
192+
| `p` | Normal/Diff | Set selected commit(s) to be picked |
193+
| `r` | Normal/Diff | Set selected commit(s) to be reworded |
194+
| `e` | Normal/Diff | Set selected commit(s) to be edited |
195+
| `s` | Normal/Diff | Set selected commit(s) to be squashed |
196+
| `f` | Normal/Diff | Set selected commit(s) to be fixed-up |
197+
| `d` | Normal | Set selected commit(s) to be dropped |
198+
| `d` | Diff | Show full commit diff |
199+
| `E` | Normal | Edit the command of an editable action |
200+
| `v` | Normal/Diff | Enter and exit visual mode (for selection) |
201+
| `I` | Normal | Insert a new line |
202+
| `Control+d` | Normal | Duplicate the selected line |
203+
| `Delete` | Normal/Diff | Remove selected lines |
204+
| `!` | Normal/Diff | Open todo file in external editor |
205+
| `Control+z` | Normal/Diff | Undo the previous change |
206+
| `Control+y` | Normal/Diff | Redo the previously undone change |
207+
| `c` | Normal/Diff | Show commit information |
208+
| Down | Diff | Scroll view down |
209+
| Up | Diff | Scroll view up |
210+
| Left | Diff | Scroll view left |
211+
| Right | Diff | Scroll view right |
212+
| Home | Diff | Scroll view to the top |
213+
| End | Diff | Scroll view to the end |
214+
| PageUp | Diff | Scroll view a step up |
215+
| PageDown | Diff | Scroll view a step down |
215216
216217
## Supported Platforms
217218

readme/customization.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ Most keys can be changed to any printable character or supported special charact
122122
| `inputForceRebase` | W | String | Key for forcing a rebase |
123123
| `inputHelp` | ? | String | Key for showing the help |
124124
| `inputInsertLine` | I | String | Key for inserting a new line |
125+
| `inputDuplicateLine` | Control+d | String | Key for duplicating the selected line |
125126
| `inputMoveDown` | Down | String | Key for moving the cursor down |
126127
| `inputMoveEnd` | End | String | Key for moving the cursor to the end of the list |
127128
| `inputMoveHome` | Home | String | Key for moving the cursor to the top of the list |

src/config/key_bindings.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ pub(crate) struct KeyBindings {
4646
pub(crate) help: Vec<String>,
4747
/// Key bindings for inserting a line.
4848
pub(crate) insert_line: Vec<String>,
49+
/// Key bindings for duplicating a line.
50+
pub(crate) duplicate_line: Vec<String>,
4951

5052
/// Key bindings for moving down.
5153
pub(crate) move_down: Vec<String>,
@@ -139,6 +141,7 @@ impl KeyBindings {
139141
force_rebase: get_input(git_config, "interactive-rebase-tool.inputForceRebase", "W")?,
140142
help: get_input(git_config, "interactive-rebase-tool.inputHelp", "?")?,
141143
insert_line: get_input(git_config, "interactive-rebase-tool.insertLine", "I")?,
144+
duplicate_line: get_input(git_config, "interactive-rebase-tool.inputDuplicateLine", "control+d")?,
142145
move_down: get_input(git_config, "interactive-rebase-tool.inputMoveDown", "Down")?,
143146
move_end: get_input(git_config, "interactive-rebase-tool.inputMoveEnd", "End")?,
144147
move_home: get_input(git_config, "interactive-rebase-tool.inputMoveHome", "Home")?,
@@ -253,6 +256,7 @@ mod tests {
253256
config_test!(force_rebase, "inputForceRebase", "W");
254257
config_test!(help, "inputHelp", "?");
255258
config_test!(insert_line, "insertLine", "I");
259+
config_test!(duplicate_line, "inputDuplicateLine", "Controld");
256260
config_test!(move_down, "inputMoveDown", "Down");
257261
config_test!(move_end, "inputMoveEnd", "End");
258262
config_test!(move_home, "inputMoveHome", "Home");

src/input/key_bindings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub(crate) struct KeyBindings {
6262
pub(crate) force_rebase: Vec<Event>,
6363
/// Key bindings for inserting a line.
6464
pub(crate) insert_line: Vec<Event>,
65+
/// Key bindings for inserting a line.
66+
pub(crate) duplicate_line: Vec<Event>,
6567
/// Key bindings for moving down.
6668
pub(crate) move_down: Vec<Event>,
6769
/// Key bindings for moving down a step.
@@ -131,6 +133,7 @@ impl KeyBindings {
131133
force_abort: map_keybindings(&key_bindings.force_abort),
132134
force_rebase: map_keybindings(&key_bindings.force_rebase),
133135
insert_line: map_keybindings(&key_bindings.insert_line),
136+
duplicate_line: map_keybindings(&key_bindings.duplicate_line),
134137
move_down: map_keybindings(&key_bindings.move_down),
135138
move_down_step: map_keybindings(&key_bindings.move_down_step),
136139
move_end: map_keybindings(&key_bindings.move_end),

src/input/standard_event.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ pub(crate) enum StandardEvent {
9595
ToggleVisualMode,
9696
/// The insert line meta event.
9797
InsertLine,
98+
/// The duplicate line meta event.
99+
DuplicateLine,
98100
/// Fixup specific action to toggle the c option.
99101
FixupKeepMessage,
100102
/// Fixup specific action to toggle the C option.

src/modules/list.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,18 @@ impl List {
421421
results.state(State::Insert);
422422
}
423423

424+
fn duplicate_line(&mut self) {
425+
let mut todo_file = self.todo_file.lock();
426+
427+
if let Some(selected_line) = todo_file.get_selected_line() {
428+
if selected_line.is_duplicatable() {
429+
let new_line = selected_line.clone();
430+
let selected_line_index = todo_file.get_selected_line_index();
431+
todo_file.add_line(selected_line_index + 1, new_line);
432+
}
433+
}
434+
}
435+
424436
fn update_list_view_data(&mut self, context: &RenderContext) -> &ViewData {
425437
let todo_file = self.todo_file.lock();
426438
let is_visual_mode = self.state == ListState::Visual;
@@ -558,6 +570,7 @@ impl List {
558570
e if key_bindings.force_abort.contains(&e) => Event::from(StandardEvent::ForceAbort),
559571
e if key_bindings.force_rebase.contains(&e) => Event::from(StandardEvent::ForceRebase),
560572
e if key_bindings.insert_line.contains(&e) => Event::from(StandardEvent::InsertLine),
573+
e if key_bindings.duplicate_line.contains(&e) => Event::from(StandardEvent::DuplicateLine),
561574
e if key_bindings.move_down.contains(&e) => Event::from(StandardEvent::MoveCursorDown),
562575
e if key_bindings.move_down_step.contains(&e) => Event::from(StandardEvent::MoveCursorPageDown),
563576
e if key_bindings.move_end.contains(&e) => Event::from(StandardEvent::MoveCursorEnd),
@@ -695,6 +708,7 @@ impl List {
695708
StandardEvent::ActionBreak => self.action_break(),
696709
StandardEvent::Edit => self.edit(),
697710
StandardEvent::InsertLine => self.insert_line(&mut results),
711+
StandardEvent::DuplicateLine => self.duplicate_line(),
698712
StandardEvent::ShowCommit => self.show_commit(&mut results),
699713
StandardEvent::FixupKeepMessage => self.toggle_option("-C"),
700714
StandardEvent::FixupKeepMessageWithEditor => self.toggle_option("-c"),

src/modules/list/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod abort_and_rebase;
22
mod activate;
33
mod change_action;
4+
mod duplicate_line;
45
mod edit_mode;
56
mod external_editor;
67
mod help;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use super::*;
2+
use crate::{action_line, assert_rendered_output, assert_results, process::Artifact};
3+
4+
#[test]
5+
fn duplicate_line_duplicatable() {
6+
testers::module(
7+
&["pick aaa c1"],
8+
&[Event::from(StandardEvent::DuplicateLine)],
9+
None,
10+
|mut test_context| {
11+
let mut module = List::new(&test_context.app_data());
12+
assert_results!(
13+
test_context.handle_event(&mut module),
14+
Artifact::Event(Event::from(StandardEvent::DuplicateLine))
15+
);
16+
assert_rendered_output!(
17+
Body test_context.build_view_data(&mut module),
18+
action_line!(Selected Pick "aaa", "c1"),
19+
action_line!(Pick "aaa", "c1")
20+
);
21+
},
22+
);
23+
}
24+
25+
#[test]
26+
fn duplicate_line_not_duplicatable() {
27+
testers::module(
28+
&["break"],
29+
&[Event::from(StandardEvent::DuplicateLine)],
30+
None,
31+
|mut test_context| {
32+
let mut module = List::new(&test_context.app_data());
33+
assert_results!(
34+
test_context.handle_event(&mut module),
35+
Artifact::Event(Event::from(StandardEvent::DuplicateLine))
36+
);
37+
assert_rendered_output!(
38+
Body test_context.build_view_data(&mut module),
39+
action_line!(Selected Break)
40+
);
41+
},
42+
);
43+
}

src/modules/list/tests/help.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn normal_mode_help() {
4343
" d |Set selected commits to be dropped",
4444
" E |Edit an exec, label, reset or merge action's content",
4545
" I |Insert a new line",
46+
" Controld|Duplicate selected line",
4647
" Delete |Completely remove the selected lines",
4748
" Controlz|Undo the last change",
4849
" Controly|Redo the previous undone change",

src/modules/list/utils.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ fn build_help_lines(key_bindings: &KeyBindings, selector: HelpLinesSelector) ->
137137
"Insert a new line",
138138
HelpLinesSelector::Normal,
139139
),
140+
(
141+
&key_bindings.duplicate_line,
142+
"Duplicate selected line",
143+
HelpLinesSelector::Normal,
144+
),
140145
(
141146
&key_bindings.remove_line,
142147
"Completely remove the selected lines",

0 commit comments

Comments
 (0)