From 987b1d5c49f5d11ab9e6a9cdea21974b440ae463 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Mon, 1 Jul 2024 23:58:03 +0800 Subject: [PATCH] feat: simplify keybindings (#1241) --- yazi-config/preset/keymap.toml | 352 +++++++++++----------- yazi-config/src/keymap/control.rs | 5 +- yazi-config/src/keymap/deserializers.rs | 83 +++++ yazi-config/src/keymap/key.rs | 10 +- yazi-config/src/keymap/mod.rs | 5 +- yazi-config/src/keymap/run.rs | 43 --- yazi-config/src/lib.rs | 14 + yazi-core/src/input/snaps.rs | 6 +- yazi-core/src/tab/commands/shell.rs | 38 ++- yazi-plugin/preset/components/current.lua | 2 +- yazi-plugin/preset/setup.lua | 1 + yazi-plugin/src/utils/call.rs | 8 + 12 files changed, 323 insertions(+), 244 deletions(-) create mode 100644 yazi-config/src/keymap/deserializers.rs delete mode 100644 yazi-config/src/keymap/run.rs diff --git a/yazi-config/preset/keymap.toml b/yazi-config/preset/keymap.toml index 9e4c0493..8443f885 100644 --- a/yazi-config/preset/keymap.toml +++ b/yazi-config/preset/keymap.toml @@ -5,84 +5,84 @@ [manager] keymap = [ - { on = [ "" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, - { on = [ "" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, - { on = [ "q" ], run = "quit", desc = "Exit the process" }, - { on = [ "Q" ], run = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" }, - { on = [ "" ], run = "close", desc = "Close the current tab, or quit if it is last tab" }, - { on = [ "" ], run = "suspend", desc = "Suspend the process" }, + { on = "", run = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, + { on = "", run = "escape", desc = "Exit visual mode, clear selected, or cancel search" }, + { on = "q", run = "quit", desc = "Exit the process" }, + { on = "Q", run = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" }, + { on = "", run = "close", desc = "Close the current tab, or quit if it is last tab" }, + { on = "", run = "suspend", desc = "Suspend the process" }, # Navigation - { on = [ "k" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "j" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "k", run = "arrow -1", desc = "Move cursor up" }, + { on = "j", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" }, - { on = [ "" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "", run = "arrow 5", desc = "Move cursor down 5 lines" }, - { on = [ "" ], run = "arrow -50%", desc = "Move cursor up half page" }, - { on = [ "" ], run = "arrow 50%", desc = "Move cursor down half page" }, - { on = [ "" ], run = "arrow -100%", desc = "Move cursor up one page" }, - { on = [ "" ], run = "arrow 100%", desc = "Move cursor down one page" }, + { on = "", run = "arrow -50%", desc = "Move cursor up half page" }, + { on = "", run = "arrow 50%", desc = "Move cursor down half page" }, + { on = "", run = "arrow -100%", desc = "Move cursor up one page" }, + { on = "", run = "arrow 100%", desc = "Move cursor down one page" }, - { on = [ "" ], run = "arrow -50%", desc = "Move cursor up half page" }, - { on = [ "" ], run = "arrow 50%", desc = "Move cursor down half page" }, - { on = [ "" ], run = "arrow -100%", desc = "Move cursor up one page" }, - { on = [ "" ], run = "arrow 100%", desc = "Move cursor down one page" }, + { on = "", run = "arrow -50%", desc = "Move cursor up half page" }, + { on = "", run = "arrow 50%", desc = "Move cursor down half page" }, + { on = "", run = "arrow -100%", desc = "Move cursor up one page" }, + { on = "", run = "arrow 100%", desc = "Move cursor down one page" }, - { on = [ "h" ], run = "leave", desc = "Go back to the parent directory" }, - { on = [ "l" ], run = "enter", desc = "Enter the child directory" }, + { on = "h", run = "leave", desc = "Go back to the parent directory" }, + { on = "l", run = "enter", desc = "Enter the child directory" }, - { on = [ "H" ], run = "back", desc = "Go back to the previous directory" }, - { on = [ "L" ], run = "forward", desc = "Go forward to the next directory" }, + { on = "H", run = "back", desc = "Go back to the previous directory" }, + { on = "L", run = "forward", desc = "Go forward to the next directory" }, - { on = [ "" ], run = "seek -5", desc = "Seek up 5 units in the preview" }, - { on = [ "" ], run = "seek 5", desc = "Seek down 5 units in the preview" }, - { on = [ "" ], run = "seek -5", desc = "Seek up 5 units in the preview" }, - { on = [ "" ], run = "seek 5", desc = "Seek down 5 units in the preview" }, + { on = "", run = "seek -5", desc = "Seek up 5 units in the preview" }, + { on = "", run = "seek 5", desc = "Seek down 5 units in the preview" }, + { on = "", run = "seek -5", desc = "Seek up 5 units in the preview" }, + { on = "", run = "seek 5", desc = "Seek down 5 units in the preview" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "leave", desc = "Go back to the parent directory" }, - { on = [ "" ], run = "enter", desc = "Enter the child directory" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "leave", desc = "Go back to the parent directory" }, + { on = "", run = "enter", desc = "Enter the child directory" }, { on = [ "g", "g" ], run = "arrow -99999999", desc = "Move cursor to the top" }, - { on = [ "G" ], run = "arrow 99999999", desc = "Move cursor to the bottom" }, + { on = "G", run = "arrow 99999999", desc = "Move cursor to the bottom" }, # Selection - { on = [ "" ], run = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" }, - { on = [ "v" ], run = "visual_mode", desc = "Enter visual mode (selection mode)" }, - { on = [ "V" ], run = "visual_mode --unset", desc = "Enter visual mode (unset mode)" }, - { on = [ "" ], run = "select_all --state=true", desc = "Select all files" }, - { on = [ "" ], run = "select_all --state=none", desc = "Inverse selection of all files" }, + { on = "", run = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" }, + { on = "v", run = "visual_mode", desc = "Enter visual mode (selection mode)" }, + { on = "V", run = "visual_mode --unset", desc = "Enter visual mode (unset mode)" }, + { on = "", run = "select_all --state=true", desc = "Select all files" }, + { on = "", run = "select_all --state=none", desc = "Inverse selection of all files" }, # Operation - { on = [ "o" ], run = "open", desc = "Open the selected files" }, - { on = [ "O" ], run = "open --interactive", desc = "Open the selected files interactively" }, - { on = [ "" ], run = "open", desc = "Open the selected files" }, - { on = [ "" ], run = "open --interactive", desc = "Open the selected files interactively" }, - { on = [ "y" ], run = "yank", desc = "Copy the selected files" }, - { on = [ "Y" ], run = "unyank", desc = "Cancel the yank status of files" }, - { on = [ "x" ], run = "yank --cut", desc = "Cut the selected files" }, - { on = [ "X" ], run = "unyank", desc = "Cancel the yank status of files" }, - { on = [ "p" ], run = "paste", desc = "Paste the files" }, - { on = [ "P" ], run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" }, - { on = [ "-" ], run = "link", desc = "Symlink the absolute path of files" }, - { on = [ "_" ], run = "link --relative", desc = "Symlink the relative path of files" }, - { on = [ "d" ], run = "remove", desc = "Move the files to the trash" }, - { on = [ "D" ], run = "remove --permanently", desc = "Permanently delete the files" }, - { on = [ "a" ], run = "create", desc = "Create a file or directory (ends with / for directories)" }, - { on = [ "r" ], run = "rename --cursor=before_ext", desc = "Rename a file or directory" }, - { on = [ ";" ], run = "shell", desc = "Run a shell command" }, - { on = [ ":" ], run = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" }, - { on = [ "." ], run = "hidden toggle", desc = "Toggle the visibility of hidden files" }, - { on = [ "s" ], run = "search fd", desc = "Search files by name using fd" }, - { on = [ "S" ], run = "search rg", desc = "Search files by content using ripgrep" }, - { on = [ "" ], run = "search none", desc = "Cancel the ongoing search" }, - { on = [ "z" ], run = "plugin zoxide", desc = "Jump to a directory using zoxide" }, - { on = [ "Z" ], run = "plugin fzf", desc = "Jump to a directory, or reveal a file using fzf" }, + { on = "o", run = "open", desc = "Open the selected files" }, + { on = "O", run = "open --interactive", desc = "Open the selected files interactively" }, + { on = "", run = "open", desc = "Open the selected files" }, + { on = "", run = "open --interactive", desc = "Open the selected files interactively" }, + { on = "y", run = "yank", desc = "Copy the selected files" }, + { on = "Y", run = "unyank", desc = "Cancel the yank status of files" }, + { on = "x", run = "yank --cut", desc = "Cut the selected files" }, + { on = "X", run = "unyank", desc = "Cancel the yank status of files" }, + { on = "p", run = "paste", desc = "Paste the files" }, + { on = "P", run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" }, + { on = "-", run = "link", desc = "Symlink the absolute path of files" }, + { on = "_", run = "link --relative", desc = "Symlink the relative path of files" }, + { on = "d", run = "remove", desc = "Move the files to the trash" }, + { on = "D", run = "remove --permanently", desc = "Permanently delete the files" }, + { on = "a", run = "create", desc = "Create a file or directory (ends with / for directories)" }, + { on = "r", run = "rename --cursor=before_ext", desc = "Rename a file or directory" }, + { on = ";", run = "shell --interactive", desc = "Run a shell command" }, + { on = ":", run = "shell --block --interactive", desc = "Run a shell command (block the UI until the command finishes)" }, + { on = ".", run = "hidden toggle", desc = "Toggle the visibility of hidden files" }, + { on = "s", run = "search fd", desc = "Search files by name using fd" }, + { on = "S", run = "search rg", desc = "Search files by content using ripgrep" }, + { on = "", run = "search none", desc = "Cancel the ongoing search" }, + { on = "z", run = "plugin zoxide", desc = "Jump to a directory using zoxide" }, + { on = "Z", run = "plugin fzf", desc = "Jump to a directory, or reveal a file using fzf" }, # Linemode { on = [ "m", "s" ], run = "linemode size", desc = "Set linemode to size" }, @@ -97,13 +97,13 @@ keymap = [ { on = [ "c", "n" ], run = "copy name_without_ext", desc = "Copy the name of the file without the extension" }, # Filter - { on = [ "f" ], run = "filter --smart", desc = "Filter the files" }, + { on = "f", run = "filter --smart", desc = "Filter the files" }, # Find - { on = [ "/" ], run = "find --smart", desc = "Find next file" }, - { on = [ "?" ], run = "find --previous --smart", desc = "Find previous file" }, - { on = [ "n" ], run = "find_arrow", desc = "Go to next found file" }, - { on = [ "N" ], run = "find_arrow --previous", desc = "Go to previous found file" }, + { on = "/", run = "find --smart", desc = "Find next file" }, + { on = "?", run = "find --previous --smart", desc = "Find previous file" }, + { on = "n", run = "find_arrow", desc = "Go to next found file" }, + { on = "N", run = "find_arrow --previous", desc = "Go to previous found file" }, # Sorting { on = [ ",", "m" ], run = "sort modified --reverse=no", desc = "Sort by modified time" }, @@ -120,26 +120,26 @@ keymap = [ { on = [ ",", "S" ], run = "sort size --reverse", desc = "Sort by size (reverse)" }, # Tabs - { on = [ "t" ], run = "tab_create --current", desc = "Create a new tab using the current path" }, + { on = "t", run = "tab_create --current", desc = "Create a new tab using the current path" }, - { on = [ "1" ], run = "tab_switch 0", desc = "Switch to the first tab" }, - { on = [ "2" ], run = "tab_switch 1", desc = "Switch to the second tab" }, - { on = [ "3" ], run = "tab_switch 2", desc = "Switch to the third tab" }, - { on = [ "4" ], run = "tab_switch 3", desc = "Switch to the fourth tab" }, - { on = [ "5" ], run = "tab_switch 4", desc = "Switch to the fifth tab" }, - { on = [ "6" ], run = "tab_switch 5", desc = "Switch to the sixth tab" }, - { on = [ "7" ], run = "tab_switch 6", desc = "Switch to the seventh tab" }, - { on = [ "8" ], run = "tab_switch 7", desc = "Switch to the eighth tab" }, - { on = [ "9" ], run = "tab_switch 8", desc = "Switch to the ninth tab" }, + { on = "1", run = "tab_switch 0", desc = "Switch to the first tab" }, + { on = "2", run = "tab_switch 1", desc = "Switch to the second tab" }, + { on = "3", run = "tab_switch 2", desc = "Switch to the third tab" }, + { on = "4", run = "tab_switch 3", desc = "Switch to the fourth tab" }, + { on = "5", run = "tab_switch 4", desc = "Switch to the fifth tab" }, + { on = "6", run = "tab_switch 5", desc = "Switch to the sixth tab" }, + { on = "7", run = "tab_switch 6", desc = "Switch to the seventh tab" }, + { on = "8", run = "tab_switch 7", desc = "Switch to the eighth tab" }, + { on = "9", run = "tab_switch 8", desc = "Switch to the ninth tab" }, - { on = [ "[" ], run = "tab_switch -1 --relative", desc = "Switch to the previous tab" }, - { on = [ "]" ], run = "tab_switch 1 --relative", desc = "Switch to the next tab" }, + { on = "[", run = "tab_switch -1 --relative", desc = "Switch to the previous tab" }, + { on = "]", run = "tab_switch 1 --relative", desc = "Switch to the next tab" }, - { on = [ "{" ], run = "tab_swap -1", desc = "Swap the current tab with the previous tab" }, - { on = [ "}" ], run = "tab_swap 1", desc = "Swap the current tab with the next tab" }, + { on = "{", run = "tab_swap -1", desc = "Swap the current tab with the previous tab" }, + { on = "}", run = "tab_swap 1", desc = "Swap the current tab with the next tab" }, # Tasks - { on = [ "w" ], run = "tasks_show", desc = "Show the tasks manager" }, + { on = "w", run = "tasks_show", desc = "Show the tasks manager" }, # Goto { on = [ "g", "h" ], run = "cd ~", desc = "Go to the home directory" }, @@ -148,161 +148,161 @@ keymap = [ { on = [ "g", "" ], run = "cd --interactive", desc = "Go to a directory interactively" }, # Help - { on = [ "~" ], run = "help", desc = "Open help" }, + { on = "~", run = "help", desc = "Open help" }, ] [tasks] keymap = [ - { on = [ "" ], run = "close", desc = "Hide the task manager" }, - { on = [ "" ], run = "close", desc = "Hide the task manager" }, - { on = [ "" ], run = "close", desc = "Hide the task manager" }, - { on = [ "w" ], run = "close", desc = "Hide the task manager" }, + { on = "", run = "close", desc = "Hide the task manager" }, + { on = "", run = "close", desc = "Hide the task manager" }, + { on = "", run = "close", desc = "Hide the task manager" }, + { on = "w", run = "close", desc = "Hide the task manager" }, - { on = [ "k" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "j" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "k", run = "arrow -1", desc = "Move cursor up" }, + { on = "j", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "inspect", desc = "Inspect the task" }, - { on = [ "x" ], run = "cancel", desc = "Cancel the task" }, + { on = "", run = "inspect", desc = "Inspect the task" }, + { on = "x", run = "cancel", desc = "Cancel the task" }, - { on = [ "~" ], run = "help", desc = "Open help" } + { on = "~", run = "help", desc = "Open help" } ] [select] keymap = [ - { on = [ "" ], run = "close", desc = "Cancel selection" }, - { on = [ "" ], run = "close", desc = "Cancel selection" }, - { on = [ "" ], run = "close", desc = "Cancel selection" }, - { on = [ "" ], run = "close --submit", desc = "Submit the selection" }, + { on = "", run = "close", desc = "Cancel selection" }, + { on = "", run = "close", desc = "Cancel selection" }, + { on = "", run = "close", desc = "Cancel selection" }, + { on = "", run = "close --submit", desc = "Submit the selection" }, - { on = [ "k" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "j" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "k", run = "arrow -1", desc = "Move cursor up" }, + { on = "j", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "", run = "arrow 5", desc = "Move cursor down 5 lines" }, - { on = [ "~" ], run = "help", desc = "Open help" } + { on = "~", run = "help", desc = "Open help" } ] [input] keymap = [ - { on = [ "" ], run = "close", desc = "Cancel input" }, - { on = [ "" ], run = "close --submit", desc = "Submit the input" }, - { on = [ "" ], run = "escape", desc = "Go back the normal mode, or cancel input" }, - { on = [ "" ], run = "escape", desc = "Go back the normal mode, or cancel input" }, + { on = "", run = "close", desc = "Cancel input" }, + { on = "", run = "close --submit", desc = "Submit the input" }, + { on = "", run = "escape", desc = "Go back the normal mode, or cancel input" }, + { on = "", run = "escape", desc = "Go back the normal mode, or cancel input" }, # Mode - { on = [ "i" ], run = "insert", desc = "Enter insert mode" }, - { on = [ "a" ], run = "insert --append", desc = "Enter append mode" }, - { on = [ "I" ], run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" }, - { on = [ "A" ], run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" }, - { on = [ "v" ], run = "visual", desc = "Enter visual mode" }, - { on = [ "V" ], run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" }, + { on = "i", run = "insert", desc = "Enter insert mode" }, + { on = "a", run = "insert --append", desc = "Enter append mode" }, + { on = "I", run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" }, + { on = "A", run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" }, + { on = "v", run = "visual", desc = "Enter visual mode" }, + { on = "V", run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" }, # Character-wise movement - { on = [ "h" ], run = "move -1", desc = "Move back a character" }, - { on = [ "l" ], run = "move 1", desc = "Move forward a character" }, - { on = [ "" ], run = "move -1", desc = "Move back a character" }, - { on = [ "" ], run = "move 1", desc = "Move forward a character" }, - { on = [ "" ], run = "move -1", desc = "Move back a character" }, - { on = [ "" ], run = "move 1", desc = "Move forward a character" }, + { on = "h", run = "move -1", desc = "Move back a character" }, + { on = "l", run = "move 1", desc = "Move forward a character" }, + { on = "", run = "move -1", desc = "Move back a character" }, + { on = "", run = "move 1", desc = "Move forward a character" }, + { on = "", run = "move -1", desc = "Move back a character" }, + { on = "", run = "move 1", desc = "Move forward a character" }, # Word-wise movement - { on = [ "b" ], run = "backward", desc = "Move back to the start of the current or previous word" }, - { on = [ "w" ], run = "forward", desc = "Move forward to the start of the next word" }, - { on = [ "e" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" }, - { on = [ "" ], run = "backward", desc = "Move back to the start of the current or previous word" }, - { on = [ "" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" }, + { on = "b", run = "backward", desc = "Move back to the start of the current or previous word" }, + { on = "w", run = "forward", desc = "Move forward to the start of the next word" }, + { on = "e", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" }, + { on = "", run = "backward", desc = "Move back to the start of the current or previous word" }, + { on = "", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" }, # Line-wise movement - { on = [ "0" ], run = "move -999", desc = "Move to the BOL" }, - { on = [ "$" ], run = "move 999", desc = "Move to the EOL" }, - { on = [ "" ], run = "move -999", desc = "Move to the BOL" }, - { on = [ "" ], run = "move 999", desc = "Move to the EOL" }, - { on = [ "" ], run = "move -999", desc = "Move to the BOL" }, - { on = [ "" ], run = "move 999", desc = "Move to the EOL" }, + { on = "0", run = "move -999", desc = "Move to the BOL" }, + { on = "$", run = "move 999", desc = "Move to the EOL" }, + { on = "", run = "move -999", desc = "Move to the BOL" }, + { on = "", run = "move 999", desc = "Move to the EOL" }, + { on = "", run = "move -999", desc = "Move to the BOL" }, + { on = "", run = "move 999", desc = "Move to the EOL" }, # Delete - { on = [ "" ], run = "backspace", desc = "Delete the character before the cursor" }, - { on = [ "" ], run = "backspace --under", desc = "Delete the character under the cursor" }, - { on = [ "" ], run = "backspace", desc = "Delete the character before the cursor" }, - { on = [ "" ], run = "backspace --under", desc = "Delete the character under the cursor" }, + { on = "", run = "backspace", desc = "Delete the character before the cursor" }, + { on = "", run = "backspace --under", desc = "Delete the character under the cursor" }, + { on = "", run = "backspace", desc = "Delete the character before the cursor" }, + { on = "", run = "backspace --under", desc = "Delete the character under the cursor" }, # Kill - { on = [ "" ], run = "kill bol", desc = "Kill backwards to the BOL" }, - { on = [ "" ], run = "kill eol", desc = "Kill forwards to the EOL" }, - { on = [ "" ], run = "kill backward", desc = "Kill backwards to the start of the current word" }, - { on = [ "" ], run = "kill forward", desc = "Kill forwards to the end of the current word" }, + { on = "", run = "kill bol", desc = "Kill backwards to the BOL" }, + { on = "", run = "kill eol", desc = "Kill forwards to the EOL" }, + { on = "", run = "kill backward", desc = "Kill backwards to the start of the current word" }, + { on = "", run = "kill forward", desc = "Kill forwards to the end of the current word" }, # Cut/Yank/Paste - { on = [ "d" ], run = "delete --cut", desc = "Cut the selected characters" }, - { on = [ "D" ], run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" }, - { on = [ "c" ], run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" }, - { on = [ "C" ], run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" }, - { on = [ "x" ], run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" }, - { on = [ "y" ], run = "yank", desc = "Copy the selected characters" }, - { on = [ "p" ], run = "paste", desc = "Paste the copied characters after the cursor" }, - { on = [ "P" ], run = "paste --before", desc = "Paste the copied characters before the cursor" }, + { on = "d", run = "delete --cut", desc = "Cut the selected characters" }, + { on = "D", run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" }, + { on = "c", run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" }, + { on = "C", run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" }, + { on = "x", run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" }, + { on = "y", run = "yank", desc = "Copy the selected characters" }, + { on = "p", run = "paste", desc = "Paste the copied characters after the cursor" }, + { on = "P", run = "paste --before", desc = "Paste the copied characters before the cursor" }, # Undo/Redo - { on = [ "u" ], run = "undo", desc = "Undo the last operation" }, - { on = [ "" ], run = "redo", desc = "Redo the last operation" }, + { on = "u", run = "undo", desc = "Undo the last operation" }, + { on = "", run = "redo", desc = "Redo the last operation" }, # Help - { on = [ "~" ], run = "help", desc = "Open help" } + { on = "~", run = "help", desc = "Open help" } ] [completion] keymap = [ - { on = [ "" ], run = "close", desc = "Cancel completion" }, - { on = [ "" ], run = "close --submit", desc = "Submit the completion" }, - { on = [ "" ], run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" }, + { on = "", run = "close", desc = "Cancel completion" }, + { on = "", run = "close --submit", desc = "Submit the completion" }, + { on = "", run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "~" ], run = "help", desc = "Open help" } + { on = "~", run = "help", desc = "Open help" } ] [help] keymap = [ - { on = [ "" ], run = "escape", desc = "Clear the filter, or hide the help" }, - { on = [ "" ], run = "escape", desc = "Clear the filter, or hide the help" }, - { on = [ "q" ], run = "close", desc = "Exit the process" }, - { on = [ "" ], run = "close", desc = "Hide the help" }, + { on = "", run = "escape", desc = "Clear the filter, or hide the help" }, + { on = "", run = "escape", desc = "Clear the filter, or hide the help" }, + { on = "q", run = "close", desc = "Exit the process" }, + { on = "", run = "close", desc = "Hide the help" }, # Navigation - { on = [ "k" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "j" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "k", run = "arrow -1", desc = "Move cursor up" }, + { on = "j", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" }, - { on = [ "" ], run = "arrow -1", desc = "Move cursor up" }, - { on = [ "" ], run = "arrow 1", desc = "Move cursor down" }, + { on = "", run = "arrow -1", desc = "Move cursor up" }, + { on = "", run = "arrow 1", desc = "Move cursor down" }, - { on = [ "" ], run = "arrow -5", desc = "Move cursor up 5 lines" }, - { on = [ "" ], run = "arrow 5", desc = "Move cursor down 5 lines" }, + { on = "", run = "arrow -5", desc = "Move cursor up 5 lines" }, + { on = "", run = "arrow 5", desc = "Move cursor down 5 lines" }, # Filtering - { on = [ "/" ], run = "filter", desc = "Apply a filter for the help items" }, + { on = "/", run = "filter", desc = "Apply a filter for the help items" }, ] diff --git a/yazi-config/src/keymap/control.rs b/yazi-config/src/keymap/control.rs index 5ad84928..85c6e906 100644 --- a/yazi-config/src/keymap/control.rs +++ b/yazi-config/src/keymap/control.rs @@ -7,8 +7,9 @@ use super::Key; #[derive(Debug, Default, Deserialize)] pub struct Control { + #[serde(deserialize_with = "super::deserialize_on")] pub on: Vec, - #[serde(deserialize_with = "super::run_deserialize")] + #[serde(deserialize_with = "super::deserialize_run")] pub run: Vec, pub desc: Option, } @@ -24,7 +25,7 @@ impl Control { #[inline] pub fn run(&self) -> String { - self.run.iter().map(|e| e.to_string()).collect::>().join("; ") + self.run.iter().map(|c| c.to_string()).collect::>().join("; ") } #[inline] diff --git a/yazi-config/src/keymap/deserializers.rs b/yazi-config/src/keymap/deserializers.rs new file mode 100644 index 00000000..dea0a226 --- /dev/null +++ b/yazi-config/src/keymap/deserializers.rs @@ -0,0 +1,83 @@ +use std::{fmt, str::FromStr}; + +use anyhow::Result; +use serde::{de::{self, Visitor}, Deserializer}; +use yazi_shared::event::Cmd; + +use crate::keymap::Key; + +pub(super) fn deserialize_on<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct OnVisitor; + + impl<'de> Visitor<'de> for OnVisitor { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a `on` string or array of strings within keymap.toml") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut cmds = vec![]; + while let Some(value) = &seq.next_element::()? { + cmds.push(Key::from_str(value).map_err(de::Error::custom)?); + } + if cmds.is_empty() { + return Err(de::Error::custom("`on` within keymap.toml cannot be empty")); + } + Ok(cmds) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(vec![Key::from_str(value).map_err(de::Error::custom)?]) + } + } + + deserializer.deserialize_any(OnVisitor) +} + +pub(super) fn deserialize_run<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct RunVisitor; + + impl<'de> Visitor<'de> for RunVisitor { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a `run` string or array of strings within keymap.toml") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut cmds = vec![]; + while let Some(value) = &seq.next_element::()? { + cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?); + } + if cmds.is_empty() { + return Err(de::Error::custom("`run` within keymap.toml cannot be empty")); + } + Ok(cmds) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(vec![Cmd::from_str(value).map_err(de::Error::custom)?]) + } + } + + deserializer.deserialize_any(RunVisitor) +} diff --git a/yazi-config/src/keymap/key.rs b/yazi-config/src/keymap/key.rs index a7fef406..93998705 100644 --- a/yazi-config/src/keymap/key.rs +++ b/yazi-config/src/keymap/key.rs @@ -2,10 +2,8 @@ use std::{fmt::{Display, Write}, str::FromStr}; use anyhow::bail; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; -use serde::Deserialize; -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)] -#[serde(try_from = "String")] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Key { pub code: KeyCode, pub shift: bool, @@ -126,12 +124,6 @@ impl FromStr for Key { } } -impl TryFrom for Key { - type Error = anyhow::Error; - - fn try_from(s: String) -> Result { Self::from_str(&s) } -} - impl Display for Key { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if let Some(c) = self.plain() { diff --git a/yazi-config/src/keymap/mod.rs b/yazi-config/src/keymap/mod.rs index 7de322c3..6c330dd3 100644 --- a/yazi-config/src/keymap/mod.rs +++ b/yazi-config/src/keymap/mod.rs @@ -1,12 +1,11 @@ mod control; mod cow; +mod deserializers; mod key; mod keymap; -mod run; pub use control::*; pub use cow::*; +use deserializers::*; pub use key::*; pub use keymap::*; -#[allow(unused_imports)] -pub use run::*; diff --git a/yazi-config/src/keymap/run.rs b/yazi-config/src/keymap/run.rs deleted file mode 100644 index 645d2349..00000000 --- a/yazi-config/src/keymap/run.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::{fmt, str::FromStr}; - -use anyhow::Result; -use serde::{de::{self, Visitor}, Deserializer}; -use yazi_shared::event::Cmd; - -pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - struct RunVisitor; - - impl<'de> Visitor<'de> for RunVisitor { - type Value = Vec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a `run` string or array of strings within keymap.toml") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - let mut cmds = vec![]; - while let Some(value) = &seq.next_element::()? { - cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?); - } - if cmds.is_empty() { - return Err(de::Error::custom("`run` within keymap.toml cannot be empty")); - } - Ok(cmds) - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - Ok(vec![Cmd::from_str(value).map_err(de::Error::custom)?]) - } - } - - deserializer.deserialize_any(RunVisitor) -} diff --git a/yazi-config/src/lib.rs b/yazi-config/src/lib.rs index a715d969..60204f59 100644 --- a/yazi-config/src/lib.rs +++ b/yazi-config/src/lib.rs @@ -58,5 +58,19 @@ pub fn init() -> anyhow::Result<()> { SELECT.init(<_>::from_str(yazi_toml)?); WHICH.init(<_>::from_str(yazi_toml)?); + // TODO: Remove in v0.3.2 + for c in &KEYMAP.manager { + for r in &c.run { + if r.name == "shell" && !r.bool("confirm") && !r.bool("interactive") { + eprintln!( + r#"WARNING: In Yazi v0.3, the behavior of the interactive `shell` (i.e., shell templates) must be explicitly specified with `--interactive`. + +Please replace e.g. `shell` with `shell --interactive`, `shell "my-template"` with `shell "my-template" --interactive`, in your keymap.toml"# + ); + return Ok(()); + } + } + } + Ok(()) } diff --git a/yazi-core/src/input/snaps.rs b/yazi-core/src/input/snaps.rs index 14b8b444..b1960bcf 100644 --- a/yazi-core/src/input/snaps.rs +++ b/yazi-core/src/input/snaps.rs @@ -19,6 +19,10 @@ impl InputSnaps { } pub(super) fn tag(&mut self, limit: usize) -> bool { + if self.versions.len() <= self.idx { + return false; + } + // Sync *current* cursor position to the *last* version: // Save offset/cursor/ect. of the *current* as the last version, // while keeping the *last* value unchanged. @@ -49,7 +53,7 @@ impl InputSnaps { } pub(super) fn redo(&mut self) -> bool { - if self.idx + 1 == self.versions.len() { + if self.idx + 1 >= self.versions.len() { return false; } diff --git a/yazi-core/src/tab/commands/shell.rs b/yazi-core/src/tab/commands/shell.rs index 4effe5db..422267be 100644 --- a/yazi-core/src/tab/commands/shell.rs +++ b/yazi-core/src/tab/commands/shell.rs @@ -1,25 +1,27 @@ use std::borrow::Cow; use yazi_config::{open::Opener, popup::InputCfg}; -use yazi_proxy::{InputProxy, TasksProxy}; +use yazi_proxy::{AppProxy, InputProxy, TasksProxy}; use yazi_shared::event::Cmd; use crate::tab::Tab; pub struct Opt { - run: String, - block: bool, - orphan: bool, - confirm: bool, + run: String, + block: bool, + orphan: bool, + confirm: bool, + interactive: bool, } impl From for Opt { fn from(mut c: Cmd) -> Self { Self { - run: c.take_first_str().unwrap_or_default(), - block: c.bool("block"), - orphan: c.bool("orphan"), - confirm: c.bool("confirm"), + run: c.take_first_str().unwrap_or_default(), + block: c.bool("block"), + orphan: c.bool("orphan"), + confirm: c.bool("confirm"), + interactive: c.bool("interactive"), } } } @@ -31,6 +33,24 @@ impl Tab { } let mut opt = opt.into() as Opt; + + // TODO: Remove in v0.3.2 + if !opt.interactive && !opt.confirm { + AppProxy::notify_error( + "`shell` command", + r#"In Yazi v0.3, the behavior of the interactive `shell` (i.e., shell templates) must be explicitly specified with `--interactive`. + +Please replace e.g. `shell` with `shell --interactive`, `shell "my-template"` with `shell "my-template" --interactive`, in your keymap.toml"#, + ); + return; + } else if opt.interactive && opt.confirm { + AppProxy::notify_error( + "`shell` command", + "The `shell` command cannot specify both `--confirm` and `--interactive` at the same time.", + ); + return; + } + let selected = self.hovered_and_selected(true).cloned().collect(); tokio::spawn(async move { diff --git a/yazi-plugin/preset/components/current.lua b/yazi-plugin/preset/components/current.lua index 839fed8f..c79bcb26 100644 --- a/yazi-plugin/preset/components/current.lua +++ b/yazi-plugin/preset/components/current.lua @@ -55,7 +55,7 @@ function Current:click(event, up) ya.manager_emit("arrow", { event.y + f.offset - f.hovered.idx }) if event.is_right then - ya.manager_emit("open", { hovered = true }) + ya.manager_emit("open", {}) end end diff --git a/yazi-plugin/preset/setup.lua b/yazi-plugin/preset/setup.lua index a6adcbb9..bba7d57e 100644 --- a/yazi-plugin/preset/setup.lua +++ b/yazi-plugin/preset/setup.lua @@ -1,3 +1,4 @@ +os.setlocale("") package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path require("dds"):setup() diff --git a/yazi-plugin/src/utils/call.rs b/yazi-plugin/src/utils/call.rs index c788aea7..2a2655a1 100644 --- a/yazi-plugin/src/utils/call.rs +++ b/yazi-plugin/src/utils/call.rs @@ -49,6 +49,14 @@ impl Utils { })?, )?; + ya.raw_set( + "input_emit", + lua.create_function(|_, (name, args): (String, Table)| { + emit!(Call(Cmd { name, args: Self::parse_args(args)? }, Layer::Input)); + Ok(()) + })?, + )?; + Ok(()) } }