Migrate keymap and settings + edit predictions rename (#23834)
- [x] snake case keymap properties - [x] flatten actions - [x] keymap migration + notfication - [x] settings migration + notification - [x] inline completions -> edit predictions ### future: - keymap notification doesn't show up on start up, only on keymap save. this is existing bug in zed, will be addressed in seperate PR. Release Notes: - Added a notification for deprecated settings and keymaps, allowing you to migrate them with a single click. A backup of your existing keymap and settings will be created in your home directory. - Modified some keymap actions and settings for consistency. --------- Co-authored-by: Piotr Osiewicz <piotr@zed.dev> Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
1 parent
2265d18119
commit
308e063ddc
58 files changed
+2106
-617
No files matched your search
Generated
+12
@@ -7836,6 +7836,17 @@ dependencies = [
|
|||||||
"paste",
|
"paste",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrator"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"collections",
|
||||||
|
"convert_case 0.7.1",
|
||||||
|
"pretty_assertions",
|
||||||
|
"tree-sitter",
|
||||||
|
"tree-sitter-json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mimalloc"
|
name = "mimalloc"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@@ -11980,6 +11991,7 @@ dependencies = [
|
|||||||
"gpui",
|
"gpui",
|
||||||
"indoc",
|
"indoc",
|
||||||
"log",
|
"log",
|
||||||
|
"migrator",
|
||||||
"paths",
|
"paths",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"release_channel",
|
"release_channel",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ members = [
|
|||||||
"crates/markdown_preview",
|
"crates/markdown_preview",
|
||||||
"crates/media",
|
"crates/media",
|
||||||
"crates/menu",
|
"crates/menu",
|
||||||
|
"crates/migrator",
|
||||||
"crates/multi_buffer",
|
"crates/multi_buffer",
|
||||||
"crates/node_runtime",
|
"crates/node_runtime",
|
||||||
"crates/notifications",
|
"crates/notifications",
|
||||||
@@ -279,6 +280,7 @@ markdown = { path = "crates/markdown" }
|
|||||||
markdown_preview = { path = "crates/markdown_preview" }
|
markdown_preview = { path = "crates/markdown_preview" }
|
||||||
media = { path = "crates/media" }
|
media = { path = "crates/media" }
|
||||||
menu = { path = "crates/menu" }
|
menu = { path = "crates/menu" }
|
||||||
|
migrator = { path = "crates/migrator" }
|
||||||
multi_buffer = { path = "crates/multi_buffer" }
|
multi_buffer = { path = "crates/multi_buffer" }
|
||||||
node_runtime = { path = "crates/node_runtime" }
|
node_runtime = { path = "crates/node_runtime" }
|
||||||
notifications = { path = "crates/notifications" }
|
notifications = { path = "crates/notifications" }
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
"ctrl-q": "zed::Quit",
|
"ctrl-q": "zed::Quit",
|
||||||
"f11": "zed::ToggleFullScreen",
|
"f11": "zed::ToggleFullScreen",
|
||||||
"ctrl-alt-z": "zeta::RateCompletions",
|
"ctrl-alt-z": "zeta::RateCompletions",
|
||||||
"ctrl-shift-i": "inline_completion::ToggleMenu"
|
"ctrl-shift-i": "edit_prediction::ToggleMenu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -145,17 +145,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && mode == full && inline_completion",
|
"context": "Editor && mode == full && edit_prediction",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"alt-]": "editor::NextInlineCompletion",
|
"alt-]": "editor::NextEditPrediction",
|
||||||
"alt-[": "editor::PreviousInlineCompletion",
|
"alt-[": "editor::PreviousEditPrediction",
|
||||||
"alt-right": "editor::AcceptPartialInlineCompletion"
|
"alt-right": "editor::AcceptPartialEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && !inline_completion",
|
"context": "Editor && !edit_prediction",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"alt-\\": "editor::ShowInlineCompletion"
|
"alt-\\": "editor::ShowEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -348,15 +348,15 @@
|
|||||||
"ctrl-k ctrl-l": "editor::ToggleFold",
|
"ctrl-k ctrl-l": "editor::ToggleFold",
|
||||||
"ctrl-k ctrl-[": "editor::FoldRecursive",
|
"ctrl-k ctrl-[": "editor::FoldRecursive",
|
||||||
"ctrl-k ctrl-]": "editor::UnfoldRecursive",
|
"ctrl-k ctrl-]": "editor::UnfoldRecursive",
|
||||||
"ctrl-k ctrl-1": ["editor::FoldAtLevel", { "level": 1 }],
|
"ctrl-k ctrl-1": ["editor::FoldAtLevel", 1],
|
||||||
"ctrl-k ctrl-2": ["editor::FoldAtLevel", { "level": 2 }],
|
"ctrl-k ctrl-2": ["editor::FoldAtLevel", 2],
|
||||||
"ctrl-k ctrl-3": ["editor::FoldAtLevel", { "level": 3 }],
|
"ctrl-k ctrl-3": ["editor::FoldAtLevel", 3],
|
||||||
"ctrl-k ctrl-4": ["editor::FoldAtLevel", { "level": 4 }],
|
"ctrl-k ctrl-4": ["editor::FoldAtLevel", 4],
|
||||||
"ctrl-k ctrl-5": ["editor::FoldAtLevel", { "level": 5 }],
|
"ctrl-k ctrl-5": ["editor::FoldAtLevel", 5],
|
||||||
"ctrl-k ctrl-6": ["editor::FoldAtLevel", { "level": 6 }],
|
"ctrl-k ctrl-6": ["editor::FoldAtLevel", 6],
|
||||||
"ctrl-k ctrl-7": ["editor::FoldAtLevel", { "level": 7 }],
|
"ctrl-k ctrl-7": ["editor::FoldAtLevel", 7],
|
||||||
"ctrl-k ctrl-8": ["editor::FoldAtLevel", { "level": 8 }],
|
"ctrl-k ctrl-8": ["editor::FoldAtLevel", 8],
|
||||||
"ctrl-k ctrl-9": ["editor::FoldAtLevel", { "level": 9 }],
|
"ctrl-k ctrl-9": ["editor::FoldAtLevel", 9],
|
||||||
"ctrl-k ctrl-0": "editor::FoldAll",
|
"ctrl-k ctrl-0": "editor::FoldAll",
|
||||||
"ctrl-k ctrl-j": "editor::UnfoldAll",
|
"ctrl-k ctrl-j": "editor::UnfoldAll",
|
||||||
"ctrl-space": "editor::ShowCompletions",
|
"ctrl-space": "editor::ShowCompletions",
|
||||||
@@ -432,14 +432,14 @@
|
|||||||
"ctrl-alt-s": "workspace::SaveAll",
|
"ctrl-alt-s": "workspace::SaveAll",
|
||||||
"ctrl-k m": "language_selector::Toggle",
|
"ctrl-k m": "language_selector::Toggle",
|
||||||
"escape": "workspace::Unfollow",
|
"escape": "workspace::Unfollow",
|
||||||
"ctrl-k ctrl-left": ["workspace::ActivatePaneInDirection", "Left"],
|
"ctrl-k ctrl-left": "workspace::ActivatePaneLeft",
|
||||||
"ctrl-k ctrl-right": ["workspace::ActivatePaneInDirection", "Right"],
|
"ctrl-k ctrl-right": "workspace::ActivatePaneRight",
|
||||||
"ctrl-k ctrl-up": ["workspace::ActivatePaneInDirection", "Up"],
|
"ctrl-k ctrl-up": "workspace::ActivatePaneUp",
|
||||||
"ctrl-k ctrl-down": ["workspace::ActivatePaneInDirection", "Down"],
|
"ctrl-k ctrl-down": "workspace::ActivatePaneDown",
|
||||||
"ctrl-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
"ctrl-k shift-left": "workspace::SwapPaneLeft",
|
||||||
"ctrl-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
"ctrl-k shift-right": "workspace::SwapPaneRight",
|
||||||
"ctrl-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
"ctrl-k shift-up": "workspace::SwapPaneUp",
|
||||||
"ctrl-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
"ctrl-k shift-down": "workspace::SwapPaneDown",
|
||||||
"ctrl-shift-x": "zed::Extensions",
|
"ctrl-shift-x": "zed::Extensions",
|
||||||
"ctrl-shift-r": "task::Rerun",
|
"ctrl-shift-r": "task::Rerun",
|
||||||
"ctrl-alt-r": "task::Rerun",
|
"ctrl-alt-r": "task::Rerun",
|
||||||
@@ -453,8 +453,8 @@
|
|||||||
{
|
{
|
||||||
"context": "ApplicationMenu",
|
"context": "ApplicationMenu",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"left": ["app_menu::NavigateApplicationMenuInDirection", "Left"],
|
"left": "app_menu::ActivateMenuLeft",
|
||||||
"right": ["app_menu::NavigateApplicationMenuInDirection", "Right"]
|
"right": "app_menu::ActivateMenuRight"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Bindings from Sublime Text
|
// Bindings from Sublime Text
|
||||||
@@ -502,16 +502,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && inline_completion",
|
"context": "Editor && edit_prediction",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
// Changing the modifier currently breaks accepting while you also an LSP completions menu open
|
// Changing the modifier currently breaks accepting while you also an LSP completions menu open
|
||||||
"alt-enter": "editor::AcceptInlineCompletion"
|
"alt-enter": "editor::AcceptEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && inline_completion && !inline_completion_requires_modifier",
|
"context": "Editor && edit_prediction && !edit_prediction_requires_modifier",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"tab": "editor::AcceptInlineCompletion"
|
"tab": "editor::AcceptEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"fn-f": "zed::ToggleFullScreen",
|
"fn-f": "zed::ToggleFullScreen",
|
||||||
"ctrl-cmd-f": "zed::ToggleFullScreen",
|
"ctrl-cmd-f": "zed::ToggleFullScreen",
|
||||||
"ctrl-shift-z": "zeta::RateCompletions",
|
"ctrl-shift-z": "zeta::RateCompletions",
|
||||||
"ctrl-shift-i": "inline_completion::ToggleMenu"
|
"ctrl-shift-i": "edit_prediction::ToggleMenu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -155,19 +155,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && mode == full && inline_completion",
|
"context": "Editor && mode == full && edit_prediction",
|
||||||
"use_key_equivalents": true,
|
"use_key_equivalents": true,
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"alt-tab": "editor::NextInlineCompletion",
|
"alt-tab": "editor::NextEditPrediction",
|
||||||
"alt-shift-tab": "editor::PreviousInlineCompletion",
|
"alt-shift-tab": "editor::PreviousEditPrediction",
|
||||||
"ctrl-cmd-right": "editor::AcceptPartialInlineCompletion"
|
"ctrl-cmd-right": "editor::AcceptPartialEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && !inline_completion",
|
"context": "Editor && !edit_prediction",
|
||||||
"use_key_equivalents": true,
|
"use_key_equivalents": true,
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"alt-tab": "editor::ShowInlineCompletion"
|
"alt-tab": "editor::ShowEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -413,15 +413,15 @@
|
|||||||
"cmd-k cmd-l": "editor::ToggleFold",
|
"cmd-k cmd-l": "editor::ToggleFold",
|
||||||
"cmd-k cmd-[": "editor::FoldRecursive",
|
"cmd-k cmd-[": "editor::FoldRecursive",
|
||||||
"cmd-k cmd-]": "editor::UnfoldRecursive",
|
"cmd-k cmd-]": "editor::UnfoldRecursive",
|
||||||
"cmd-k cmd-1": ["editor::FoldAtLevel", { "level": 1 }],
|
"cmd-k cmd-1": ["editor::FoldAtLevel", 1],
|
||||||
"cmd-k cmd-2": ["editor::FoldAtLevel", { "level": 2 }],
|
"cmd-k cmd-2": ["editor::FoldAtLevel", 2],
|
||||||
"cmd-k cmd-3": ["editor::FoldAtLevel", { "level": 3 }],
|
"cmd-k cmd-3": ["editor::FoldAtLevel", 3],
|
||||||
"cmd-k cmd-4": ["editor::FoldAtLevel", { "level": 4 }],
|
"cmd-k cmd-4": ["editor::FoldAtLevel", 4],
|
||||||
"cmd-k cmd-5": ["editor::FoldAtLevel", { "level": 5 }],
|
"cmd-k cmd-5": ["editor::FoldAtLevel", 5],
|
||||||
"cmd-k cmd-6": ["editor::FoldAtLevel", { "level": 6 }],
|
"cmd-k cmd-6": ["editor::FoldAtLevel", 6],
|
||||||
"cmd-k cmd-7": ["editor::FoldAtLevel", { "level": 7 }],
|
"cmd-k cmd-7": ["editor::FoldAtLevel", 7],
|
||||||
"cmd-k cmd-8": ["editor::FoldAtLevel", { "level": 8 }],
|
"cmd-k cmd-8": ["editor::FoldAtLevel", 8],
|
||||||
"cmd-k cmd-9": ["editor::FoldAtLevel", { "level": 9 }],
|
"cmd-k cmd-9": ["editor::FoldAtLevel", 9],
|
||||||
"cmd-k cmd-0": "editor::FoldAll",
|
"cmd-k cmd-0": "editor::FoldAll",
|
||||||
"cmd-k cmd-j": "editor::UnfoldAll",
|
"cmd-k cmd-j": "editor::UnfoldAll",
|
||||||
// Using `ctrl-space` in Zed requires disabling the macOS global shortcut.
|
// Using `ctrl-space` in Zed requires disabling the macOS global shortcut.
|
||||||
@@ -509,14 +509,14 @@
|
|||||||
"cmd-alt-s": "workspace::SaveAll",
|
"cmd-alt-s": "workspace::SaveAll",
|
||||||
"cmd-k m": "language_selector::Toggle",
|
"cmd-k m": "language_selector::Toggle",
|
||||||
"escape": "workspace::Unfollow",
|
"escape": "workspace::Unfollow",
|
||||||
"cmd-k cmd-left": ["workspace::ActivatePaneInDirection", "Left"],
|
"cmd-k cmd-left": "workspace::ActivatePaneLeft",
|
||||||
"cmd-k cmd-right": ["workspace::ActivatePaneInDirection", "Right"],
|
"cmd-k cmd-right": "workspace::ActivatePaneRight",
|
||||||
"cmd-k cmd-up": ["workspace::ActivatePaneInDirection", "Up"],
|
"cmd-k cmd-up": "workspace::ActivatePaneUp",
|
||||||
"cmd-k cmd-down": ["workspace::ActivatePaneInDirection", "Down"],
|
"cmd-k cmd-down": "workspace::ActivatePaneDown",
|
||||||
"cmd-k shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
"cmd-k shift-left": "workspace::SwapPaneLeft",
|
||||||
"cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
"cmd-k shift-right": "workspace::SwapPaneRight",
|
||||||
"cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
"cmd-k shift-up": "workspace::SwapPaneUp",
|
||||||
"cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
"cmd-k shift-down": "workspace::SwapPaneDown",
|
||||||
"cmd-shift-x": "zed::Extensions"
|
"cmd-shift-x": "zed::Extensions"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -580,17 +580,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && inline_completion",
|
"context": "Editor && edit_prediction",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
// Changing the modifier currently breaks accepting while you also an LSP completions menu open
|
// Changing the modifier currently breaks accepting while you also an LSP completions menu open
|
||||||
"alt-tab": "editor::AcceptInlineCompletion"
|
"alt-tab": "editor::AcceptEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "Editor && inline_completion && !inline_completion_requires_modifier",
|
"context": "Editor && edit_prediction && !edit_prediction_requires_modifier",
|
||||||
"use_key_equivalents": true,
|
"use_key_equivalents": true,
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"tab": "editor::AcceptInlineCompletion"
|
"tab": "editor::AcceptEditPrediction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+98
-98
@@ -2,8 +2,8 @@
|
|||||||
{
|
{
|
||||||
"context": "VimControl && !menu",
|
"context": "VimControl && !menu",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"i": ["vim::PushOperator", { "Object": { "around": false } }],
|
"i": ["vim::PushObject", { "around": false }],
|
||||||
"a": ["vim::PushOperator", { "Object": { "around": true } }],
|
"a": ["vim::PushObject", { "around": true }],
|
||||||
"left": "vim::Left",
|
"left": "vim::Left",
|
||||||
"h": "vim::Left",
|
"h": "vim::Left",
|
||||||
"backspace": "vim::Backspace",
|
"backspace": "vim::Backspace",
|
||||||
@@ -54,10 +54,10 @@
|
|||||||
// "b": "vim::PreviousSubwordStart",
|
// "b": "vim::PreviousSubwordStart",
|
||||||
// "e": "vim::NextSubwordEnd",
|
// "e": "vim::NextSubwordEnd",
|
||||||
// "g e": "vim::PreviousSubwordEnd",
|
// "g e": "vim::PreviousSubwordEnd",
|
||||||
"shift-w": ["vim::NextWordStart", { "ignorePunctuation": true }],
|
"shift-w": ["vim::NextWordStart", { "ignore_punctuation": true }],
|
||||||
"shift-e": ["vim::NextWordEnd", { "ignorePunctuation": true }],
|
"shift-e": ["vim::NextWordEnd", { "ignore_punctuation": true }],
|
||||||
"shift-b": ["vim::PreviousWordStart", { "ignorePunctuation": true }],
|
"shift-b": ["vim::PreviousWordStart", { "ignore_punctuation": true }],
|
||||||
"g shift-e": ["vim::PreviousWordEnd", { "ignorePunctuation": true }],
|
"g shift-e": ["vim::PreviousWordEnd", { "ignore_punctuation": true }],
|
||||||
"/": "vim::Search",
|
"/": "vim::Search",
|
||||||
"g /": "pane::DeploySearch",
|
"g /": "pane::DeploySearch",
|
||||||
"?": ["vim::Search", { "backwards": true }],
|
"?": ["vim::Search", { "backwards": true }],
|
||||||
@@ -70,20 +70,20 @@
|
|||||||
"[ {": ["vim::UnmatchedBackward", { "char": "{" }],
|
"[ {": ["vim::UnmatchedBackward", { "char": "{" }],
|
||||||
"] )": ["vim::UnmatchedForward", { "char": ")" }],
|
"] )": ["vim::UnmatchedForward", { "char": ")" }],
|
||||||
"[ (": ["vim::UnmatchedBackward", { "char": "(" }],
|
"[ (": ["vim::UnmatchedBackward", { "char": "(" }],
|
||||||
"f": ["vim::PushOperator", { "FindForward": { "before": false } }],
|
"f": ["vim::PushFindForward", { "before": false }],
|
||||||
"t": ["vim::PushOperator", { "FindForward": { "before": true } }],
|
"t": ["vim::PushFindForward", { "before": true }],
|
||||||
"shift-f": ["vim::PushOperator", { "FindBackward": { "after": false } }],
|
"shift-f": ["vim::PushFindBackward", { "after": false }],
|
||||||
"shift-t": ["vim::PushOperator", { "FindBackward": { "after": true } }],
|
"shift-t": ["vim::PushFindBackward", { "after": true }],
|
||||||
"m": ["vim::PushOperator", "Mark"],
|
"m": "vim::PushMark",
|
||||||
"'": ["vim::PushOperator", { "Jump": { "line": true } }],
|
"'": ["vim::PushJump", { "line": true }],
|
||||||
"`": ["vim::PushOperator", { "Jump": { "line": false } }],
|
"`": ["vim::PushJump", { "line": false }],
|
||||||
";": "vim::RepeatFind",
|
";": "vim::RepeatFind",
|
||||||
",": "vim::RepeatFindReversed",
|
",": "vim::RepeatFindReversed",
|
||||||
"ctrl-o": "pane::GoBack",
|
"ctrl-o": "pane::GoBack",
|
||||||
"ctrl-i": "pane::GoForward",
|
"ctrl-i": "pane::GoForward",
|
||||||
"ctrl-]": "editor::GoToDefinition",
|
"ctrl-]": "editor::GoToDefinition",
|
||||||
"escape": ["vim::SwitchMode", "Normal"],
|
"escape": "vim::SwitchToNormalMode",
|
||||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
"ctrl-[": "vim::SwitchToNormalMode",
|
||||||
"v": "vim::ToggleVisual",
|
"v": "vim::ToggleVisual",
|
||||||
"shift-v": "vim::ToggleVisualLine",
|
"shift-v": "vim::ToggleVisualLine",
|
||||||
"ctrl-g": "vim::ShowLocation",
|
"ctrl-g": "vim::ShowLocation",
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
"ctrl-e": "vim::LineDown",
|
"ctrl-e": "vim::LineDown",
|
||||||
"ctrl-y": "vim::LineUp",
|
"ctrl-y": "vim::LineUp",
|
||||||
// "g" commands
|
// "g" commands
|
||||||
"g r": ["vim::PushOperator", "ReplaceWithRegister"],
|
"g r": "vim::PushReplaceWithRegister",
|
||||||
"g g": "vim::StartOfDocument",
|
"g g": "vim::StartOfDocument",
|
||||||
"g h": "editor::Hover",
|
"g h": "editor::Hover",
|
||||||
"g t": "pane::ActivateNextItem",
|
"g t": "pane::ActivateNextItem",
|
||||||
@@ -125,17 +125,17 @@
|
|||||||
"g .": "editor::ToggleCodeActions", // zed specific
|
"g .": "editor::ToggleCodeActions", // zed specific
|
||||||
"g shift-a": "editor::FindAllReferences", // zed specific
|
"g shift-a": "editor::FindAllReferences", // zed specific
|
||||||
"g space": "editor::OpenExcerpts", // zed specific
|
"g space": "editor::OpenExcerpts", // zed specific
|
||||||
"g *": ["vim::MoveToNext", { "partialWord": true }],
|
"g *": ["vim::MoveToNext", { "partial_word": true }],
|
||||||
"g #": ["vim::MoveToPrev", { "partialWord": true }],
|
"g #": ["vim::MoveToPrev", { "partial_word": true }],
|
||||||
"g j": ["vim::Down", { "displayLines": true }],
|
"g j": ["vim::Down", { "display_lines": true }],
|
||||||
"g down": ["vim::Down", { "displayLines": true }],
|
"g down": ["vim::Down", { "display_lines": true }],
|
||||||
"g k": ["vim::Up", { "displayLines": true }],
|
"g k": ["vim::Up", { "display_lines": true }],
|
||||||
"g up": ["vim::Up", { "displayLines": true }],
|
"g up": ["vim::Up", { "display_lines": true }],
|
||||||
"g $": ["vim::EndOfLine", { "displayLines": true }],
|
"g $": ["vim::EndOfLine", { "display_lines": true }],
|
||||||
"g end": ["vim::EndOfLine", { "displayLines": true }],
|
"g end": ["vim::EndOfLine", { "display_lines": true }],
|
||||||
"g 0": ["vim::StartOfLine", { "displayLines": true }],
|
"g 0": ["vim::StartOfLine", { "display_lines": true }],
|
||||||
"g home": ["vim::StartOfLine", { "displayLines": true }],
|
"g home": ["vim::StartOfLine", { "display_lines": true }],
|
||||||
"g ^": ["vim::FirstNonWhitespace", { "displayLines": true }],
|
"g ^": ["vim::FirstNonWhitespace", { "display_lines": true }],
|
||||||
"g v": "vim::RestoreVisualSelection",
|
"g v": "vim::RestoreVisualSelection",
|
||||||
"g ]": "editor::GoToDiagnostic",
|
"g ]": "editor::GoToDiagnostic",
|
||||||
"g [": "editor::GoToPrevDiagnostic",
|
"g [": "editor::GoToPrevDiagnostic",
|
||||||
@@ -147,7 +147,7 @@
|
|||||||
"shift-l": "vim::WindowBottom",
|
"shift-l": "vim::WindowBottom",
|
||||||
"q": "vim::ToggleRecord",
|
"q": "vim::ToggleRecord",
|
||||||
"shift-q": "vim::ReplayLastRecording",
|
"shift-q": "vim::ReplayLastRecording",
|
||||||
"@": ["vim::PushOperator", "ReplayRegister"],
|
"@": "vim::PushReplayRegister",
|
||||||
// z commands
|
// z commands
|
||||||
"z enter": ["workspace::SendKeystrokes", "z t ^"],
|
"z enter": ["workspace::SendKeystrokes", "z t ^"],
|
||||||
"z -": ["workspace::SendKeystrokes", "z b ^"],
|
"z -": ["workspace::SendKeystrokes", "z b ^"],
|
||||||
@@ -166,8 +166,8 @@
|
|||||||
"z f": "editor::FoldSelectedRanges",
|
"z f": "editor::FoldSelectedRanges",
|
||||||
"z shift-m": "editor::FoldAll",
|
"z shift-m": "editor::FoldAll",
|
||||||
"z shift-r": "editor::UnfoldAll",
|
"z shift-r": "editor::UnfoldAll",
|
||||||
"shift-z shift-q": ["pane::CloseActiveItem", { "saveIntent": "skip" }],
|
"shift-z shift-q": ["pane::CloseActiveItem", { "save_intent": "skip" }],
|
||||||
"shift-z shift-z": ["pane::CloseActiveItem", { "saveIntent": "saveAll" }],
|
"shift-z shift-z": ["pane::CloseActiveItem", { "save_intent": "save_all" }],
|
||||||
// Count support
|
// Count support
|
||||||
"1": ["vim::Number", 1],
|
"1": ["vim::Number", 1],
|
||||||
"2": ["vim::Number", 2],
|
"2": ["vim::Number", 2],
|
||||||
@@ -194,13 +194,13 @@
|
|||||||
"escape": "editor::Cancel",
|
"escape": "editor::Cancel",
|
||||||
":": "command_palette::Toggle",
|
":": "command_palette::Toggle",
|
||||||
".": "vim::Repeat",
|
".": "vim::Repeat",
|
||||||
"c": ["vim::PushOperator", "Change"],
|
"c": "vim::PushChange",
|
||||||
"shift-c": "vim::ChangeToEndOfLine",
|
"shift-c": "vim::ChangeToEndOfLine",
|
||||||
"d": ["vim::PushOperator", "Delete"],
|
"d": "vim::PushDelete",
|
||||||
"shift-d": "vim::DeleteToEndOfLine",
|
"shift-d": "vim::DeleteToEndOfLine",
|
||||||
"shift-j": "vim::JoinLines",
|
"shift-j": "vim::JoinLines",
|
||||||
"g shift-j": "vim::JoinLinesNoWhitespace",
|
"g shift-j": "vim::JoinLinesNoWhitespace",
|
||||||
"y": ["vim::PushOperator", "Yank"],
|
"y": "vim::PushYank",
|
||||||
"shift-y": "vim::YankLine",
|
"shift-y": "vim::YankLine",
|
||||||
"i": "vim::InsertBefore",
|
"i": "vim::InsertBefore",
|
||||||
"shift-i": "vim::InsertFirstNonWhitespace",
|
"shift-i": "vim::InsertFirstNonWhitespace",
|
||||||
@@ -217,19 +217,19 @@
|
|||||||
"shift-p": ["vim::Paste", { "before": true }],
|
"shift-p": ["vim::Paste", { "before": true }],
|
||||||
"u": "vim::Undo",
|
"u": "vim::Undo",
|
||||||
"ctrl-r": "vim::Redo",
|
"ctrl-r": "vim::Redo",
|
||||||
"r": ["vim::PushOperator", "Replace"],
|
"r": "vim::PushReplace",
|
||||||
"s": "vim::Substitute",
|
"s": "vim::Substitute",
|
||||||
"shift-s": "vim::SubstituteLine",
|
"shift-s": "vim::SubstituteLine",
|
||||||
">": ["vim::PushOperator", "Indent"],
|
">": "vim::PushIndent",
|
||||||
"<": ["vim::PushOperator", "Outdent"],
|
"<": "vim::PushOutdent",
|
||||||
"=": ["vim::PushOperator", "AutoIndent"],
|
"=": "vim::PushAutoIndent",
|
||||||
"!": ["vim::PushOperator", "ShellCommand"],
|
"!": "vim::PushShellCommand",
|
||||||
"g u": ["vim::PushOperator", "Lowercase"],
|
"g u": "vim::PushLowercase",
|
||||||
"g shift-u": ["vim::PushOperator", "Uppercase"],
|
"g shift-u": "vim::PushUppercase",
|
||||||
"g ~": ["vim::PushOperator", "OppositeCase"],
|
"g ~": "vim::PushOppositeCase",
|
||||||
"\"": ["vim::PushOperator", "Register"],
|
"\"": "vim::PushRegister",
|
||||||
"g w": ["vim::PushOperator", "Rewrap"],
|
"g w": "vim::PushRewrap",
|
||||||
"g q": ["vim::PushOperator", "Rewrap"],
|
"g q": "vim::PushRewrap",
|
||||||
"ctrl-pagedown": "pane::ActivateNextItem",
|
"ctrl-pagedown": "pane::ActivateNextItem",
|
||||||
"ctrl-pageup": "pane::ActivatePrevItem",
|
"ctrl-pageup": "pane::ActivatePrevItem",
|
||||||
"insert": "vim::InsertBefore",
|
"insert": "vim::InsertBefore",
|
||||||
@@ -240,7 +240,7 @@
|
|||||||
"[ d": "editor::GoToPrevDiagnostic",
|
"[ d": "editor::GoToPrevDiagnostic",
|
||||||
"] c": "editor::GoToHunk",
|
"] c": "editor::GoToHunk",
|
||||||
"[ c": "editor::GoToPrevHunk",
|
"[ c": "editor::GoToPrevHunk",
|
||||||
"g c": ["vim::PushOperator", "ToggleComments"]
|
"g c": "vim::PushToggleComments"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -265,14 +265,14 @@
|
|||||||
"y": "vim::VisualYank",
|
"y": "vim::VisualYank",
|
||||||
"shift-y": "vim::VisualYankLine",
|
"shift-y": "vim::VisualYankLine",
|
||||||
"p": "vim::Paste",
|
"p": "vim::Paste",
|
||||||
"shift-p": ["vim::Paste", { "preserveClipboard": true }],
|
"shift-p": ["vim::Paste", { "preserve_clipboard": true }],
|
||||||
"c": "vim::Substitute",
|
"c": "vim::Substitute",
|
||||||
"s": "vim::Substitute",
|
"s": "vim::Substitute",
|
||||||
"shift-r": "vim::SubstituteLine",
|
"shift-r": "vim::SubstituteLine",
|
||||||
"shift-s": "vim::SubstituteLine",
|
"shift-s": "vim::SubstituteLine",
|
||||||
"~": "vim::ChangeCase",
|
"~": "vim::ChangeCase",
|
||||||
"*": ["vim::MoveToNext", { "partialWord": true }],
|
"*": ["vim::MoveToNext", { "partial_word": true }],
|
||||||
"#": ["vim::MoveToPrev", { "partialWord": true }],
|
"#": ["vim::MoveToPrev", { "partial_word": true }],
|
||||||
"ctrl-a": "vim::Increment",
|
"ctrl-a": "vim::Increment",
|
||||||
"ctrl-x": "vim::Decrement",
|
"ctrl-x": "vim::Decrement",
|
||||||
"g ctrl-a": ["vim::Increment", { "step": true }],
|
"g ctrl-a": ["vim::Increment", { "step": true }],
|
||||||
@@ -283,19 +283,19 @@
|
|||||||
"g shift-a": "vim::VisualInsertEndOfLine",
|
"g shift-a": "vim::VisualInsertEndOfLine",
|
||||||
"shift-j": "vim::JoinLines",
|
"shift-j": "vim::JoinLines",
|
||||||
"g shift-j": "vim::JoinLinesNoWhitespace",
|
"g shift-j": "vim::JoinLinesNoWhitespace",
|
||||||
"r": ["vim::PushOperator", "Replace"],
|
"r": "vim::PushReplace",
|
||||||
"ctrl-c": ["vim::SwitchMode", "Normal"],
|
"ctrl-c": "vim::SwitchToNormalMode",
|
||||||
"ctrl-[": ["vim::SwitchMode", "Normal"],
|
"ctrl-[": "vim::SwitchToNormalMode",
|
||||||
"escape": ["vim::SwitchMode", "Normal"],
|
"escape": "vim::SwitchToNormalMode",
|
||||||
">": "vim::Indent",
|
">": "vim::Indent",
|
||||||
"<": "vim::Outdent",
|
"<": "vim::Outdent",
|
||||||
"=": "vim::AutoIndent",
|
"=": "vim::AutoIndent",
|
||||||
"!": "vim::ShellCommand",
|
"!": "vim::ShellCommand",
|
||||||
"i": ["vim::PushOperator", { "Object": { "around": false } }],
|
"i": ["vim::PushObject", { "around": false }],
|
||||||
"a": ["vim::PushOperator", { "Object": { "around": true } }],
|
"a": ["vim::PushObject", { "around": true }],
|
||||||
"g c": "vim::ToggleComments",
|
"g c": "vim::ToggleComments",
|
||||||
"g q": "vim::Rewrap",
|
"g q": "vim::Rewrap",
|
||||||
"\"": ["vim::PushOperator", "Register"],
|
"\"": "vim::PushRegister",
|
||||||
// tree-sitter related commands
|
// tree-sitter related commands
|
||||||
"[ x": "editor::SelectLargerSyntaxNode",
|
"[ x": "editor::SelectLargerSyntaxNode",
|
||||||
"] x": "editor::SelectSmallerSyntaxNode"
|
"] x": "editor::SelectSmallerSyntaxNode"
|
||||||
@@ -310,19 +310,19 @@
|
|||||||
"ctrl-x": null,
|
"ctrl-x": null,
|
||||||
"ctrl-x ctrl-o": "editor::ShowCompletions",
|
"ctrl-x ctrl-o": "editor::ShowCompletions",
|
||||||
"ctrl-x ctrl-a": "assistant::InlineAssist", // zed specific
|
"ctrl-x ctrl-a": "assistant::InlineAssist", // zed specific
|
||||||
"ctrl-x ctrl-c": "editor::ShowInlineCompletion", // zed specific
|
"ctrl-x ctrl-c": "editor::ShowEditPrediction", // zed specific
|
||||||
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
|
"ctrl-x ctrl-l": "editor::ToggleCodeActions", // zed specific
|
||||||
"ctrl-x ctrl-z": "editor::Cancel",
|
"ctrl-x ctrl-z": "editor::Cancel",
|
||||||
"ctrl-w": "editor::DeleteToPreviousWordStart",
|
"ctrl-w": "editor::DeleteToPreviousWordStart",
|
||||||
"ctrl-u": "editor::DeleteToBeginningOfLine",
|
"ctrl-u": "editor::DeleteToBeginningOfLine",
|
||||||
"ctrl-t": "vim::Indent",
|
"ctrl-t": "vim::Indent",
|
||||||
"ctrl-d": "vim::Outdent",
|
"ctrl-d": "vim::Outdent",
|
||||||
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
|
"ctrl-k": ["vim::PushDigraph", {}],
|
||||||
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-v": ["vim::PushLiteral", {}],
|
||||||
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
|
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
|
||||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-q": ["vim::PushLiteral", {}],
|
||||||
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-shift-q": ["vim::PushLiteral", {}],
|
||||||
"ctrl-r": ["vim::PushOperator", "Register"],
|
"ctrl-r": "vim::PushRegister",
|
||||||
"insert": "vim::ToggleReplace",
|
"insert": "vim::ToggleReplace",
|
||||||
"ctrl-o": "vim::TemporaryNormal"
|
"ctrl-o": "vim::TemporaryNormal"
|
||||||
}
|
}
|
||||||
@@ -357,11 +357,11 @@
|
|||||||
"ctrl-c": "vim::NormalBefore",
|
"ctrl-c": "vim::NormalBefore",
|
||||||
"ctrl-[": "vim::NormalBefore",
|
"ctrl-[": "vim::NormalBefore",
|
||||||
"escape": "vim::NormalBefore",
|
"escape": "vim::NormalBefore",
|
||||||
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
|
"ctrl-k": ["vim::PushDigraph", {}],
|
||||||
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-v": ["vim::PushLiteral", {}],
|
||||||
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
|
"ctrl-shift-v": "editor::Paste", // note: this is *very* similar to ctrl-v in vim, but ctrl-shift-v on linux is the typical shortcut for paste when ctrl-v is already in use.
|
||||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-q": ["vim::PushLiteral", {}],
|
||||||
"ctrl-shift-q": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-shift-q": ["vim::PushLiteral", {}],
|
||||||
"backspace": "vim::UndoReplace",
|
"backspace": "vim::UndoReplace",
|
||||||
"tab": "vim::Tab",
|
"tab": "vim::Tab",
|
||||||
"enter": "vim::Enter",
|
"enter": "vim::Enter",
|
||||||
@@ -376,9 +376,9 @@
|
|||||||
"ctrl-c": "vim::ClearOperators",
|
"ctrl-c": "vim::ClearOperators",
|
||||||
"ctrl-[": "vim::ClearOperators",
|
"ctrl-[": "vim::ClearOperators",
|
||||||
"escape": "vim::ClearOperators",
|
"escape": "vim::ClearOperators",
|
||||||
"ctrl-k": ["vim::PushOperator", { "Digraph": {} }],
|
"ctrl-k": ["vim::PushDigraph", {}],
|
||||||
"ctrl-v": ["vim::PushOperator", { "Literal": {} }],
|
"ctrl-v": ["vim::PushLiteral", {}],
|
||||||
"ctrl-q": ["vim::PushOperator", { "Literal": {} }]
|
"ctrl-q": ["vim::PushLiteral", {}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -394,10 +394,10 @@
|
|||||||
"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
|
"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"w": "vim::Word",
|
"w": "vim::Word",
|
||||||
"shift-w": ["vim::Word", { "ignorePunctuation": true }],
|
"shift-w": ["vim::Word", { "ignore_punctuation": true }],
|
||||||
// Subword TextObject
|
// Subword TextObject
|
||||||
// "w": "vim::Subword",
|
// "w": "vim::Subword",
|
||||||
// "shift-w": ["vim::Subword", { "ignorePunctuation": true }],
|
// "shift-w": ["vim::Subword", { "ignore_punctuation": true }],
|
||||||
"t": "vim::Tag",
|
"t": "vim::Tag",
|
||||||
"s": "vim::Sentence",
|
"s": "vim::Sentence",
|
||||||
"p": "vim::Paragraph",
|
"p": "vim::Paragraph",
|
||||||
@@ -420,7 +420,7 @@
|
|||||||
">": "vim::AngleBrackets",
|
">": "vim::AngleBrackets",
|
||||||
"a": "vim::Argument",
|
"a": "vim::Argument",
|
||||||
"i": "vim::IndentObj",
|
"i": "vim::IndentObj",
|
||||||
"shift-i": ["vim::IndentObj", { "includeBelow": true }],
|
"shift-i": ["vim::IndentObj", { "include_below": true }],
|
||||||
"f": "vim::Method",
|
"f": "vim::Method",
|
||||||
"c": "vim::Class",
|
"c": "vim::Class",
|
||||||
"e": "vim::EntireFile"
|
"e": "vim::EntireFile"
|
||||||
@@ -431,14 +431,14 @@
|
|||||||
"bindings": {
|
"bindings": {
|
||||||
"c": "vim::CurrentLine",
|
"c": "vim::CurrentLine",
|
||||||
"d": "editor::Rename", // zed specific
|
"d": "editor::Rename", // zed specific
|
||||||
"s": ["vim::PushOperator", { "ChangeSurrounds": {} }]
|
"s": ["vim::PushChangeSurrounds", {}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "vim_operator == d",
|
"context": "vim_operator == d",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"d": "vim::CurrentLine",
|
"d": "vim::CurrentLine",
|
||||||
"s": ["vim::PushOperator", "DeleteSurrounds"],
|
"s": "vim::PushDeleteSurrounds",
|
||||||
"o": "editor::ToggleSelectedDiffHunks", // "d o"
|
"o": "editor::ToggleSelectedDiffHunks", // "d o"
|
||||||
"p": "editor::RevertSelectedHunks" // "d p"
|
"p": "editor::RevertSelectedHunks" // "d p"
|
||||||
}
|
}
|
||||||
@@ -477,7 +477,7 @@
|
|||||||
"context": "vim_operator == y",
|
"context": "vim_operator == y",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"y": "vim::CurrentLine",
|
"y": "vim::CurrentLine",
|
||||||
"s": ["vim::PushOperator", { "AddSurrounds": {} }]
|
"s": ["vim::PushAddSurrounds", {}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -571,30 +571,30 @@
|
|||||||
"bindings": {
|
"bindings": {
|
||||||
// window related commands (ctrl-w X)
|
// window related commands (ctrl-w X)
|
||||||
"ctrl-w": null,
|
"ctrl-w": null,
|
||||||
"ctrl-w left": ["workspace::ActivatePaneInDirection", "Left"],
|
"ctrl-w left": "workspace::ActivatePaneLeft",
|
||||||
"ctrl-w right": ["workspace::ActivatePaneInDirection", "Right"],
|
"ctrl-w right": "workspace::ActivatePaneRight",
|
||||||
"ctrl-w up": ["workspace::ActivatePaneInDirection", "Up"],
|
"ctrl-w up": "workspace::ActivatePaneUp",
|
||||||
"ctrl-w down": ["workspace::ActivatePaneInDirection", "Down"],
|
"ctrl-w down": "workspace::ActivatePaneDown",
|
||||||
"ctrl-w ctrl-h": ["workspace::ActivatePaneInDirection", "Left"],
|
"ctrl-w ctrl-h": "workspace::ActivatePaneLeft",
|
||||||
"ctrl-w ctrl-l": ["workspace::ActivatePaneInDirection", "Right"],
|
"ctrl-w ctrl-l": "workspace::ActivatePaneRight",
|
||||||
"ctrl-w ctrl-k": ["workspace::ActivatePaneInDirection", "Up"],
|
"ctrl-w ctrl-k": "workspace::ActivatePaneUp",
|
||||||
"ctrl-w ctrl-j": ["workspace::ActivatePaneInDirection", "Down"],
|
"ctrl-w ctrl-j": "workspace::ActivatePaneDown",
|
||||||
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
|
"ctrl-w h": "workspace::ActivatePaneLeft",
|
||||||
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
|
"ctrl-w l": "workspace::ActivatePaneRight",
|
||||||
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
|
"ctrl-w k": "workspace::ActivatePaneUp",
|
||||||
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"],
|
"ctrl-w j": "workspace::ActivatePaneDown",
|
||||||
"ctrl-w shift-left": ["workspace::SwapPaneInDirection", "Left"],
|
"ctrl-w shift-left": "workspace::SwapPaneLeft",
|
||||||
"ctrl-w shift-right": ["workspace::SwapPaneInDirection", "Right"],
|
"ctrl-w shift-right": "workspace::SwapPaneRight",
|
||||||
"ctrl-w shift-up": ["workspace::SwapPaneInDirection", "Up"],
|
"ctrl-w shift-up": "workspace::SwapPaneUp",
|
||||||
"ctrl-w shift-down": ["workspace::SwapPaneInDirection", "Down"],
|
"ctrl-w shift-down": "workspace::SwapPaneDown",
|
||||||
"ctrl-w shift-h": ["workspace::SwapPaneInDirection", "Left"],
|
"ctrl-w shift-h": "workspace::SwapPaneLeft",
|
||||||
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
|
"ctrl-w shift-l": "workspace::SwapPaneRight",
|
||||||
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
|
"ctrl-w shift-k": "workspace::SwapPaneUp",
|
||||||
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
|
"ctrl-w shift-j": "workspace::SwapPaneDown",
|
||||||
"ctrl-w >": ["vim::ResizePane", "Widen"],
|
"ctrl-w >": "vim::ResizePaneRight",
|
||||||
"ctrl-w <": ["vim::ResizePane", "Narrow"],
|
"ctrl-w <": "vim::ResizePaneLeft",
|
||||||
"ctrl-w -": ["vim::ResizePane", "Shorten"],
|
"ctrl-w -": "vim::ResizePaneDown",
|
||||||
"ctrl-w +": ["vim::ResizePane", "Lengthen"],
|
"ctrl-w +": "vim::ResizePaneUp",
|
||||||
"ctrl-w _": "vim::MaximizePane",
|
"ctrl-w _": "vim::MaximizePane",
|
||||||
"ctrl-w =": "vim::ResetPaneSizes",
|
"ctrl-w =": "vim::ResetPaneSizes",
|
||||||
"ctrl-w g t": "pane::ActivateNextItem",
|
"ctrl-w g t": "pane::ActivateNextItem",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
// Features that can be globally enabled or disabled
|
// Features that can be globally enabled or disabled
|
||||||
"features": {
|
"features": {
|
||||||
// Which edit prediction provider to use.
|
// Which edit prediction provider to use.
|
||||||
"inline_completion_provider": "copilot"
|
"edit_prediction_provider": "copilot"
|
||||||
},
|
},
|
||||||
// The name of a font to use for rendering text in the editor
|
// The name of a font to use for rendering text in the editor
|
||||||
"buffer_font_family": "Zed Plex Mono",
|
"buffer_font_family": "Zed Plex Mono",
|
||||||
@@ -170,7 +170,7 @@
|
|||||||
"show_signature_help_after_edits": false,
|
"show_signature_help_after_edits": false,
|
||||||
/// Whether to show the edit predictions next to the completions provided by a language server.
|
/// Whether to show the edit predictions next to the completions provided by a language server.
|
||||||
/// Only has an effect if edit prediction provider supports it.
|
/// Only has an effect if edit prediction provider supports it.
|
||||||
"show_inline_completions_in_menu": true,
|
"show_edit_predictions_in_menu": true,
|
||||||
// Whether to show wrap guides (vertical rulers) in the editor.
|
// Whether to show wrap guides (vertical rulers) in the editor.
|
||||||
// Setting this to true will show a guide at the 'preferred_line_length' value
|
// Setting this to true will show a guide at the 'preferred_line_length' value
|
||||||
// if 'soft_wrap' is set to 'preferred_line_length', and will show any
|
// if 'soft_wrap' is set to 'preferred_line_length', and will show any
|
||||||
@@ -204,11 +204,11 @@
|
|||||||
// no matter how they were inserted.
|
// no matter how they were inserted.
|
||||||
"always_treat_brackets_as_autoclosed": false,
|
"always_treat_brackets_as_autoclosed": false,
|
||||||
// Controls whether edit predictions are shown immediately (true)
|
// Controls whether edit predictions are shown immediately (true)
|
||||||
// or manually by triggering `editor::ShowInlineCompletion` (false).
|
// or manually by triggering `editor::ShowEditPrediction` (false).
|
||||||
"show_inline_completions": true,
|
"show_edit_predictions": true,
|
||||||
// Controls whether edit predictions are shown in a given language scope.
|
// Controls whether edit predictions are shown in a given language scope.
|
||||||
// Example: ["string", "comment"]
|
// Example: ["string", "comment"]
|
||||||
"inline_completions_disabled_in": [],
|
"edit_predictions_disabled_in": [],
|
||||||
// Whether to show tabs and spaces in the editor.
|
// Whether to show tabs and spaces in the editor.
|
||||||
// This setting can take four values:
|
// This setting can take four values:
|
||||||
//
|
//
|
||||||
@@ -781,7 +781,7 @@
|
|||||||
// 2. Load direnv configuration through the shell hook, works for POSIX shells and fish.
|
// 2. Load direnv configuration through the shell hook, works for POSIX shells and fish.
|
||||||
// "load_direnv": "shell_hook"
|
// "load_direnv": "shell_hook"
|
||||||
"load_direnv": "direct",
|
"load_direnv": "direct",
|
||||||
"inline_completions": {
|
"edit_predictions": {
|
||||||
// A list of globs representing files that edit predictions should be disabled for.
|
// A list of globs representing files that edit predictions should be disabled for.
|
||||||
"disabled_globs": [
|
"disabled_globs": [
|
||||||
"**/.env*",
|
"**/.env*",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use gpui::{
|
|||||||
use http_client::github::get_release_by_tag_name;
|
use http_client::github::get_release_by_tag_name;
|
||||||
use http_client::HttpClient;
|
use http_client::HttpClient;
|
||||||
use language::{
|
use language::{
|
||||||
language_settings::{all_language_settings, language_settings, InlineCompletionProvider},
|
language_settings::{all_language_settings, language_settings, EditPredictionProvider},
|
||||||
point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16,
|
point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16,
|
||||||
ToPointUtf16,
|
ToPointUtf16,
|
||||||
};
|
};
|
||||||
@@ -368,8 +368,8 @@ impl Copilot {
|
|||||||
let server_id = self.server_id;
|
let server_id = self.server_id;
|
||||||
let http = self.http.clone();
|
let http = self.http.clone();
|
||||||
let node_runtime = self.node_runtime.clone();
|
let node_runtime = self.node_runtime.clone();
|
||||||
if all_language_settings(None, cx).inline_completions.provider
|
if all_language_settings(None, cx).edit_predictions.provider
|
||||||
== InlineCompletionProvider::Copilot
|
== EditPredictionProvider::Copilot
|
||||||
{
|
{
|
||||||
if matches!(self.server, CopilotServer::Disabled) {
|
if matches!(self.server, CopilotServer::Disabled) {
|
||||||
let start_task = cx
|
let start_task = cx
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{Completion, Copilot};
|
use crate::{Completion, Copilot};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gpui::{App, Context, Entity, EntityId, Task};
|
use gpui::{App, Context, Entity, EntityId, Task};
|
||||||
use inline_completion::{Direction, InlineCompletion, InlineCompletionProvider};
|
use inline_completion::{Direction, EditPredictionProvider, InlineCompletion};
|
||||||
use language::{language_settings::AllLanguageSettings, Buffer, OffsetRangeExt, ToOffset};
|
use language::{language_settings::AllLanguageSettings, Buffer, OffsetRangeExt, ToOffset};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
@@ -48,7 +48,7 @@ impl CopilotCompletionProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineCompletionProvider for CopilotCompletionProvider {
|
impl EditPredictionProvider for CopilotCompletionProvider {
|
||||||
fn name() -> &'static str {
|
fn name() -> &'static str {
|
||||||
"copilot"
|
"copilot"
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.set_state(indoc! {"
|
cx.set_state(indoc! {"
|
||||||
@@ -436,8 +436,8 @@ mod tests {
|
|||||||
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
|
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
|
||||||
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
|
assert_eq!(editor.text(cx), "one.co\ntwo\nthree\n");
|
||||||
|
|
||||||
// AcceptInlineCompletion when there is an active suggestion inserts it.
|
// AcceptEditPrediction when there is an active suggestion inserts it.
|
||||||
editor.accept_inline_completion(&Default::default(), window, cx);
|
editor.accept_edit_prediction(&Default::default(), window, cx);
|
||||||
assert!(!editor.has_active_inline_completion());
|
assert!(!editor.has_active_inline_completion());
|
||||||
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
|
assert_eq!(editor.display_text(cx), "one.copilot2\ntwo\nthree\n");
|
||||||
assert_eq!(editor.text(cx), "one.copilot2\ntwo\nthree\n");
|
assert_eq!(editor.text(cx), "one.copilot2\ntwo\nthree\n");
|
||||||
@@ -482,7 +482,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.next_inline_completion(&Default::default(), window, cx)
|
editor.next_edit_prediction(&Default::default(), window, cx)
|
||||||
});
|
});
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
@@ -496,8 +496,8 @@ mod tests {
|
|||||||
assert_eq!(editor.text(cx), "fn foo() {\n \n}");
|
assert_eq!(editor.text(cx), "fn foo() {\n \n}");
|
||||||
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
|
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
|
||||||
|
|
||||||
// Using AcceptInlineCompletion again accepts the suggestion.
|
// Using AcceptEditPrediction again accepts the suggestion.
|
||||||
editor.accept_inline_completion(&Default::default(), window, cx);
|
editor.accept_edit_prediction(&Default::default(), window, cx);
|
||||||
assert!(!editor.has_active_inline_completion());
|
assert!(!editor.has_active_inline_completion());
|
||||||
assert_eq!(editor.text(cx), "fn foo() {\n let x = 4;\n}");
|
assert_eq!(editor.text(cx), "fn foo() {\n let x = 4;\n}");
|
||||||
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
|
assert_eq!(editor.display_text(cx), "fn foo() {\n let x = 4;\n}");
|
||||||
@@ -526,7 +526,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setup the editor with a completion request.
|
// Setup the editor with a completion request.
|
||||||
@@ -650,7 +650,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.set_state(indoc! {"
|
cx.set_state(indoc! {"
|
||||||
@@ -669,7 +669,7 @@ mod tests {
|
|||||||
vec![],
|
vec![],
|
||||||
);
|
);
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.next_inline_completion(&Default::default(), window, cx)
|
editor.next_edit_prediction(&Default::default(), window, cx)
|
||||||
});
|
});
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
@@ -740,7 +740,7 @@ mod tests {
|
|||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
editor
|
editor
|
||||||
.update(cx, |editor, window, cx| {
|
.update(cx, |editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -758,7 +758,7 @@ mod tests {
|
|||||||
editor.change_selections(None, window, cx, |s| {
|
editor.change_selections(None, window, cx, |s| {
|
||||||
s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
|
s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
|
||||||
});
|
});
|
||||||
editor.next_inline_completion(&Default::default(), window, cx);
|
editor.next_edit_prediction(&Default::default(), window, cx);
|
||||||
});
|
});
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
_ = editor.update(cx, |editor, _, cx| {
|
_ = editor.update(cx, |editor, _, cx| {
|
||||||
@@ -834,7 +834,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.set_state(indoc! {"
|
cx.set_state(indoc! {"
|
||||||
@@ -862,7 +862,7 @@ mod tests {
|
|||||||
vec![],
|
vec![],
|
||||||
);
|
);
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.next_inline_completion(&Default::default(), window, cx)
|
editor.next_edit_prediction(&Default::default(), window, cx)
|
||||||
});
|
});
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
cx.update_editor(|editor, _, cx| {
|
cx.update_editor(|editor, _, cx| {
|
||||||
@@ -930,7 +930,7 @@ mod tests {
|
|||||||
async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut TestAppContext) {
|
async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut TestAppContext) {
|
||||||
init_test(cx, |settings| {
|
init_test(cx, |settings| {
|
||||||
settings
|
settings
|
||||||
.inline_completions
|
.edit_predictions
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.disabled_globs = Some(vec![".env*".to_string()]);
|
.disabled_globs = Some(vec![".env*".to_string()]);
|
||||||
});
|
});
|
||||||
@@ -992,7 +992,7 @@ mod tests {
|
|||||||
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let copilot_provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
editor
|
editor
|
||||||
.update(cx, |editor, window, cx| {
|
.update(cx, |editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(copilot_provider), window, cx)
|
editor.set_edit_prediction_provider(Some(copilot_provider), window, cx)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -3,56 +3,64 @@ use super::*;
|
|||||||
use gpui::{action_as, action_with_deprecated_aliases};
|
use gpui::{action_as, action_with_deprecated_aliases};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use util::serde::default_true;
|
use util::serde::default_true;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectNext {
|
pub struct SelectNext {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_newest: bool,
|
pub replace_newest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectPrevious {
|
pub struct SelectPrevious {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_newest: bool,
|
pub replace_newest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MoveToBeginningOfLine {
|
pub struct MoveToBeginningOfLine {
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
pub stop_at_soft_wraps: bool,
|
pub stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectToBeginningOfLine {
|
pub struct SelectToBeginningOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) stop_at_soft_wraps: bool,
|
pub(super) stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MovePageUp {
|
pub struct MovePageUp {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) center_cursor: bool,
|
pub(super) center_cursor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MovePageDown {
|
pub struct MovePageDown {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) center_cursor: bool,
|
pub(super) center_cursor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MoveToEndOfLine {
|
pub struct MoveToEndOfLine {
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
pub stop_at_soft_wraps: bool,
|
pub stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectToEndOfLine {
|
pub struct SelectToEndOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) stop_at_soft_wraps: bool,
|
pub(super) stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ToggleCodeActions {
|
pub struct ToggleCodeActions {
|
||||||
// Display row from which the action was deployed.
|
// Display row from which the action was deployed.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -61,24 +69,28 @@ pub struct ToggleCodeActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ConfirmCompletion {
|
pub struct ConfirmCompletion {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub item_ix: Option<usize>,
|
pub item_ix: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ComposeCompletion {
|
pub struct ComposeCompletion {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub item_ix: Option<usize>,
|
pub item_ix: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ConfirmCodeAction {
|
pub struct ConfirmCodeAction {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub item_ix: Option<usize>,
|
pub item_ix: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ToggleComments {
|
pub struct ToggleComments {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub advance_downwards: bool,
|
pub advance_downwards: bool,
|
||||||
@@ -87,60 +99,70 @@ pub struct ToggleComments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct FoldAt {
|
pub struct FoldAt {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub buffer_row: MultiBufferRow,
|
pub buffer_row: MultiBufferRow,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct UnfoldAt {
|
pub struct UnfoldAt {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub buffer_row: MultiBufferRow,
|
pub buffer_row: MultiBufferRow,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MoveUpByLines {
|
pub struct MoveUpByLines {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MoveDownByLines {
|
pub struct MoveDownByLines {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectUpByLines {
|
pub struct SelectUpByLines {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SelectDownByLines {
|
pub struct SelectDownByLines {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ExpandExcerpts {
|
pub struct ExpandExcerpts {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ExpandExcerptsUp {
|
pub struct ExpandExcerptsUp {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ExpandExcerptsDown {
|
pub struct ExpandExcerptsDown {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) lines: u32,
|
pub(super) lines: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ShowCompletions {
|
pub struct ShowCompletions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(super) trigger: Option<String>,
|
pub(super) trigger: Option<String>,
|
||||||
@@ -150,23 +172,24 @@ pub struct ShowCompletions {
|
|||||||
pub struct HandleInput(pub String);
|
pub struct HandleInput(pub String);
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct DeleteToNextWordEnd {
|
pub struct DeleteToNextWordEnd {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub ignore_newlines: bool,
|
pub ignore_newlines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct DeleteToPreviousWordStart {
|
pub struct DeleteToPreviousWordStart {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub ignore_newlines: bool,
|
pub ignore_newlines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
pub struct FoldAtLevel {
|
pub struct FoldAtLevel(pub u32);
|
||||||
pub level: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SpawnNearestTask {
|
pub struct SpawnNearestTask {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub reveal: task::RevealStrategy,
|
pub reveal: task::RevealStrategy,
|
||||||
@@ -216,9 +239,9 @@ impl_actions!(
|
|||||||
gpui::actions!(
|
gpui::actions!(
|
||||||
editor,
|
editor,
|
||||||
[
|
[
|
||||||
AcceptInlineCompletion,
|
AcceptEditPrediction,
|
||||||
AcceptPartialCopilotSuggestion,
|
AcceptPartialCopilotSuggestion,
|
||||||
AcceptPartialInlineCompletion,
|
AcceptPartialEditPrediction,
|
||||||
AddSelectionAbove,
|
AddSelectionAbove,
|
||||||
AddSelectionBelow,
|
AddSelectionBelow,
|
||||||
ApplyAllDiffHunks,
|
ApplyAllDiffHunks,
|
||||||
@@ -310,7 +333,7 @@ gpui::actions!(
|
|||||||
Newline,
|
Newline,
|
||||||
NewlineAbove,
|
NewlineAbove,
|
||||||
NewlineBelow,
|
NewlineBelow,
|
||||||
NextInlineCompletion,
|
NextEditPrediction,
|
||||||
NextScreen,
|
NextScreen,
|
||||||
OpenContextMenu,
|
OpenContextMenu,
|
||||||
OpenExcerpts,
|
OpenExcerpts,
|
||||||
@@ -325,7 +348,7 @@ gpui::actions!(
|
|||||||
PageDown,
|
PageDown,
|
||||||
PageUp,
|
PageUp,
|
||||||
Paste,
|
Paste,
|
||||||
PreviousInlineCompletion,
|
PreviousEditPrediction,
|
||||||
Redo,
|
Redo,
|
||||||
RedoSelection,
|
RedoSelection,
|
||||||
Rename,
|
Rename,
|
||||||
@@ -361,7 +384,7 @@ gpui::actions!(
|
|||||||
SelectToStartOfParagraph,
|
SelectToStartOfParagraph,
|
||||||
SelectUp,
|
SelectUp,
|
||||||
ShowCharacterPalette,
|
ShowCharacterPalette,
|
||||||
ShowInlineCompletion,
|
ShowEditPrediction,
|
||||||
ShowSignatureHelp,
|
ShowSignatureHelp,
|
||||||
ShuffleLines,
|
ShuffleLines,
|
||||||
SortLinesCaseInsensitive,
|
SortLinesCaseInsensitive,
|
||||||
@@ -375,7 +398,7 @@ gpui::actions!(
|
|||||||
ToggleGitBlameInline,
|
ToggleGitBlameInline,
|
||||||
ToggleIndentGuides,
|
ToggleIndentGuides,
|
||||||
ToggleInlayHints,
|
ToggleInlayHints,
|
||||||
ToggleInlineCompletions,
|
ToggleEditPrediction,
|
||||||
ToggleLineNumbers,
|
ToggleLineNumbers,
|
||||||
SwapSelectionEnds,
|
SwapSelectionEnds,
|
||||||
SetMark,
|
SetMark,
|
||||||
|
|||||||
@@ -517,7 +517,6 @@ impl CompletionsMenu {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let color_swatch = completion
|
let color_swatch = completion
|
||||||
.color()
|
.color()
|
||||||
.map(|color| div().size_4().bg(color).rounded_sm());
|
.map(|color| div().size_4().bg(color).rounded_sm());
|
||||||
|
|||||||
+50
-50
@@ -90,7 +90,7 @@ use hover_popover::{hide_hover, HoverState};
|
|||||||
use indent_guides::ActiveIndentGuidesState;
|
use indent_guides::ActiveIndentGuidesState;
|
||||||
use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
|
use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
|
||||||
pub use inline_completion::Direction;
|
pub use inline_completion::Direction;
|
||||||
use inline_completion::{InlineCompletionProvider, InlineCompletionProviderHandle};
|
use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
|
||||||
pub use items::MAX_TAB_TITLE_LEN;
|
pub use items::MAX_TAB_TITLE_LEN;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use language::{
|
use language::{
|
||||||
@@ -674,7 +674,7 @@ pub struct Editor {
|
|||||||
pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
|
pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
|
||||||
gutter_hovered: bool,
|
gutter_hovered: bool,
|
||||||
hovered_link_state: Option<HoveredLinkState>,
|
hovered_link_state: Option<HoveredLinkState>,
|
||||||
inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
|
edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
|
||||||
code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
|
code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
|
||||||
active_inline_completion: Option<InlineCompletionState>,
|
active_inline_completion: Option<InlineCompletionState>,
|
||||||
/// Used to prevent flickering as the user types while the menu is open
|
/// Used to prevent flickering as the user types while the menu is open
|
||||||
@@ -1371,7 +1371,7 @@ impl Editor {
|
|||||||
hover_state: Default::default(),
|
hover_state: Default::default(),
|
||||||
pending_mouse_down: None,
|
pending_mouse_down: None,
|
||||||
hovered_link_state: Default::default(),
|
hovered_link_state: Default::default(),
|
||||||
inline_completion_provider: None,
|
edit_prediction_provider: None,
|
||||||
active_inline_completion: None,
|
active_inline_completion: None,
|
||||||
stale_inline_completion_in_menu: None,
|
stale_inline_completion_in_menu: None,
|
||||||
previewing_inline_completion: false,
|
previewing_inline_completion: false,
|
||||||
@@ -1524,10 +1524,10 @@ impl Editor {
|
|||||||
|
|
||||||
if self.has_active_inline_completion() {
|
if self.has_active_inline_completion() {
|
||||||
key_context.add("copilot_suggestion");
|
key_context.add("copilot_suggestion");
|
||||||
key_context.add("inline_completion");
|
key_context.add("edit_prediction");
|
||||||
|
|
||||||
if showing_completions || self.inline_completion_requires_modifier(cx) {
|
if showing_completions || self.edit_prediction_requires_modifier(cx) {
|
||||||
key_context.add("inline_completion_requires_modifier");
|
key_context.add("edit_prediction_requires_modifier");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1737,15 +1737,15 @@ impl Editor {
|
|||||||
self.semantics_provider = provider;
|
self.semantics_provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_inline_completion_provider<T>(
|
pub fn set_edit_prediction_provider<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
provider: Option<Entity<T>>,
|
provider: Option<Entity<T>>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) where
|
) where
|
||||||
T: InlineCompletionProvider,
|
T: EditPredictionProvider,
|
||||||
{
|
{
|
||||||
self.inline_completion_provider =
|
self.edit_prediction_provider =
|
||||||
provider.map(|provider| RegisteredInlineCompletionProvider {
|
provider.map(|provider| RegisteredInlineCompletionProvider {
|
||||||
_subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
|
_subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
|
||||||
if this.focus_handle.is_focused(window) {
|
if this.focus_handle.is_focused(window) {
|
||||||
@@ -1877,7 +1877,7 @@ impl Editor {
|
|||||||
|
|
||||||
pub fn toggle_inline_completions(
|
pub fn toggle_inline_completions(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &ToggleInlineCompletions,
|
_: &ToggleEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -1900,11 +1900,11 @@ impl Editor {
|
|||||||
|
|
||||||
pub fn set_show_inline_completions(
|
pub fn set_show_inline_completions(
|
||||||
&mut self,
|
&mut self,
|
||||||
show_inline_completions: Option<bool>,
|
show_edit_predictions: Option<bool>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
self.show_inline_completions_override = show_inline_completions;
|
self.show_inline_completions_override = show_edit_predictions;
|
||||||
self.refresh_inline_completion(false, true, window, cx);
|
self.refresh_inline_completion(false, true, window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1932,7 +1932,7 @@ impl Editor {
|
|||||||
|
|
||||||
scope.override_name().map_or(false, |scope_name| {
|
scope.override_name().map_or(false, |scope_name| {
|
||||||
settings
|
settings
|
||||||
.inline_completions_disabled_in
|
.edit_predictions_disabled_in
|
||||||
.iter()
|
.iter()
|
||||||
.any(|s| s == scope_name)
|
.any(|s| s == scope_name)
|
||||||
})
|
})
|
||||||
@@ -3015,7 +3015,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let trigger_in_words =
|
let trigger_in_words =
|
||||||
this.show_inline_completions_in_menu(cx) || !had_active_inline_completion;
|
this.show_edit_predictions_in_menu(cx) || !had_active_inline_completion;
|
||||||
this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
|
this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
|
||||||
linked_editing_ranges::refresh_linked_ranges(this, window, cx);
|
linked_editing_ranges::refresh_linked_ranges(this, window, cx);
|
||||||
this.refresh_inline_completion(true, false, window, cx);
|
this.refresh_inline_completion(true, false, window, cx);
|
||||||
@@ -3908,7 +3908,7 @@ impl Editor {
|
|||||||
*editor.context_menu.borrow_mut() =
|
*editor.context_menu.borrow_mut() =
|
||||||
Some(CodeContextMenu::Completions(menu));
|
Some(CodeContextMenu::Completions(menu));
|
||||||
|
|
||||||
if editor.show_inline_completions_in_menu(cx) {
|
if editor.show_edit_predictions_in_menu(cx) {
|
||||||
editor.update_visible_inline_completion(window, cx);
|
editor.update_visible_inline_completion(window, cx);
|
||||||
} else {
|
} else {
|
||||||
editor.discard_inline_completion(false, cx);
|
editor.discard_inline_completion(false, cx);
|
||||||
@@ -3922,7 +3922,7 @@ impl Editor {
|
|||||||
// If it was already hidden and we don't show inline
|
// If it was already hidden and we don't show inline
|
||||||
// completions in the menu, we should also show the
|
// completions in the menu, we should also show the
|
||||||
// inline-completion when available.
|
// inline-completion when available.
|
||||||
if was_hidden && editor.show_inline_completions_in_menu(cx) {
|
if was_hidden && editor.show_edit_predictions_in_menu(cx) {
|
||||||
editor.update_visible_inline_completion(window, cx);
|
editor.update_visible_inline_completion(window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3972,7 +3972,7 @@ impl Editor {
|
|||||||
|
|
||||||
let entries = completions_menu.entries.borrow();
|
let entries = completions_menu.entries.borrow();
|
||||||
let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
|
let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
|
||||||
if self.show_inline_completions_in_menu(cx) {
|
if self.show_edit_predictions_in_menu(cx) {
|
||||||
self.discard_inline_completion(true, cx);
|
self.discard_inline_completion(true, cx);
|
||||||
}
|
}
|
||||||
let candidate_id = mat.candidate_id;
|
let candidate_id = mat.candidate_id;
|
||||||
@@ -4653,7 +4653,7 @@ impl Editor {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let provider = self.inline_completion_provider()?;
|
let provider = self.edit_prediction_provider()?;
|
||||||
let cursor = self.selections.newest_anchor().head();
|
let cursor = self.selections.newest_anchor().head();
|
||||||
let (buffer, cursor_buffer_position) =
|
let (buffer, cursor_buffer_position) =
|
||||||
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
||||||
@@ -4694,7 +4694,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inline_completion_requires_modifier(&self, cx: &App) -> bool {
|
fn edit_prediction_requires_modifier(&self, cx: &App) -> bool {
|
||||||
let cursor = self.selections.newest_anchor().head();
|
let cursor = self.selections.newest_anchor().head();
|
||||||
|
|
||||||
self.buffer
|
self.buffer
|
||||||
@@ -4731,7 +4731,7 @@ impl Editor {
|
|||||||
buffer.file(),
|
buffer.file(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.show_inline_completions
|
.show_edit_predictions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4753,7 +4753,7 @@ impl Editor {
|
|||||||
cx: &App,
|
cx: &App,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
maybe!({
|
maybe!({
|
||||||
let provider = self.inline_completion_provider()?;
|
let provider = self.edit_prediction_provider()?;
|
||||||
if !provider.is_enabled(&buffer, buffer_position, cx) {
|
if !provider.is_enabled(&buffer, buffer_position, cx) {
|
||||||
return Some(false);
|
return Some(false);
|
||||||
}
|
}
|
||||||
@@ -4773,7 +4773,7 @@ impl Editor {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let provider = self.inline_completion_provider()?;
|
let provider = self.edit_prediction_provider()?;
|
||||||
let cursor = self.selections.newest_anchor().head();
|
let cursor = self.selections.newest_anchor().head();
|
||||||
let (buffer, cursor_buffer_position) =
|
let (buffer, cursor_buffer_position) =
|
||||||
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
||||||
@@ -4791,7 +4791,7 @@ impl Editor {
|
|||||||
|
|
||||||
pub fn show_inline_completion(
|
pub fn show_inline_completion(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &ShowInlineCompletion,
|
_: &ShowEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -4826,9 +4826,9 @@ impl Editor {
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_inline_completion(
|
pub fn next_edit_prediction(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &NextInlineCompletion,
|
_: &NextEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -4844,9 +4844,9 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn previous_inline_completion(
|
pub fn previous_edit_prediction(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &PreviousInlineCompletion,
|
_: &PreviousEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -4862,9 +4862,9 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept_inline_completion(
|
pub fn accept_edit_prediction(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &AcceptInlineCompletion,
|
_: &AcceptEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -4885,7 +4885,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.show_inline_completions_in_menu(cx) {
|
if self.show_edit_predictions_in_menu(cx) {
|
||||||
self.hide_context_menu(window, cx);
|
self.hide_context_menu(window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4904,7 +4904,7 @@ impl Editor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
InlineCompletion::Edit { edits, .. } => {
|
InlineCompletion::Edit { edits, .. } => {
|
||||||
if let Some(provider) = self.inline_completion_provider() {
|
if let Some(provider) = self.edit_prediction_provider() {
|
||||||
provider.accept(cx);
|
provider.accept(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4931,7 +4931,7 @@ impl Editor {
|
|||||||
|
|
||||||
pub fn accept_partial_inline_completion(
|
pub fn accept_partial_inline_completion(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &AcceptPartialInlineCompletion,
|
_: &AcceptPartialEditPrediction,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -4988,7 +4988,7 @@ impl Editor {
|
|||||||
self.refresh_inline_completion(true, true, window, cx);
|
self.refresh_inline_completion(true, true, window, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
} else {
|
} else {
|
||||||
self.accept_inline_completion(&Default::default(), window, cx);
|
self.accept_edit_prediction(&Default::default(), window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5003,7 +5003,7 @@ impl Editor {
|
|||||||
self.report_inline_completion_event(false, cx);
|
self.report_inline_completion_event(false, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(provider) = self.inline_completion_provider() {
|
if let Some(provider) = self.edit_prediction_provider() {
|
||||||
provider.discard(cx);
|
provider.discard(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5011,7 +5011,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn report_inline_completion_event(&self, accepted: bool, cx: &App) {
|
fn report_inline_completion_event(&self, accepted: bool, cx: &App) {
|
||||||
let Some(provider) = self.inline_completion_provider() else {
|
let Some(provider) = self.edit_prediction_provider() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5064,7 +5064,7 @@ impl Editor {
|
|||||||
cx: &App,
|
cx: &App,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if self.previewing_inline_completion
|
if self.previewing_inline_completion
|
||||||
|| !self.show_inline_completions_in_menu(cx)
|
|| !self.show_edit_predictions_in_menu(cx)
|
||||||
|| !self.should_show_inline_completions(cx)
|
|| !self.should_show_inline_completions(cx)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -5074,7 +5074,7 @@ impl Editor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_completion && self.inline_completion_requires_modifier(cx)
|
has_completion && self.edit_prediction_requires_modifier(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_inline_completion_preview(
|
fn update_inline_completion_preview(
|
||||||
@@ -5083,7 +5083,7 @@ impl Editor {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
if !self.show_inline_completions_in_menu(cx) {
|
if !self.show_edit_predictions_in_menu(cx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5103,7 +5103,7 @@ impl Editor {
|
|||||||
let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
|
let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
|
||||||
let excerpt_id = cursor.excerpt_id;
|
let excerpt_id = cursor.excerpt_id;
|
||||||
|
|
||||||
let show_in_menu = self.show_inline_completions_in_menu(cx);
|
let show_in_menu = self.show_edit_predictions_in_menu(cx);
|
||||||
let completions_menu_has_precedence = !show_in_menu
|
let completions_menu_has_precedence = !show_in_menu
|
||||||
&& (self.context_menu.borrow().is_some()
|
&& (self.context_menu.borrow().is_some()
|
||||||
|| (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
|
|| (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
|
||||||
@@ -5123,7 +5123,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.take_active_inline_completion(cx);
|
self.take_active_inline_completion(cx);
|
||||||
let provider = self.inline_completion_provider()?;
|
let provider = self.edit_prediction_provider()?;
|
||||||
|
|
||||||
let (buffer, cursor_buffer_position) =
|
let (buffer, cursor_buffer_position) =
|
||||||
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
|
||||||
@@ -5258,20 +5258,20 @@ impl Editor {
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inline_completion_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
|
pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
|
||||||
Some(self.inline_completion_provider.as_ref()?.provider.clone())
|
Some(self.edit_prediction_provider.as_ref()?.provider.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_inline_completions_in_menu(&self, cx: &App) -> bool {
|
fn show_edit_predictions_in_menu(&self, cx: &App) -> bool {
|
||||||
let by_provider = matches!(
|
let by_provider = matches!(
|
||||||
self.menu_inline_completions_policy,
|
self.menu_inline_completions_policy,
|
||||||
MenuInlineCompletionsPolicy::ByProvider
|
MenuInlineCompletionsPolicy::ByProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
by_provider
|
by_provider
|
||||||
&& EditorSettings::get_global(cx).show_inline_completions_in_menu
|
&& EditorSettings::get_global(cx).show_edit_predictions_in_menu
|
||||||
&& self
|
&& self
|
||||||
.inline_completion_provider()
|
.edit_prediction_provider()
|
||||||
.map_or(false, |provider| provider.show_completions_in_menu())
|
.map_or(false, |provider| provider.show_completions_in_menu())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5524,7 +5524,7 @@ impl Editor {
|
|||||||
window: &Window,
|
window: &Window,
|
||||||
cx: &mut Context<Editor>,
|
cx: &mut Context<Editor>,
|
||||||
) -> Option<AnyElement> {
|
) -> Option<AnyElement> {
|
||||||
let provider = self.inline_completion_provider.as_ref()?;
|
let provider = self.edit_prediction_provider.as_ref()?;
|
||||||
|
|
||||||
if provider.provider.needs_terms_acceptance(cx) {
|
if provider.provider.needs_terms_acceptance(cx) {
|
||||||
return Some(
|
return Some(
|
||||||
@@ -11808,7 +11808,7 @@ impl Editor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fold_at_level = fold_at.level;
|
let fold_at_level = fold_at.0;
|
||||||
let snapshot = self.buffer.read(cx).snapshot(cx);
|
let snapshot = self.buffer.read(cx).snapshot(cx);
|
||||||
let mut to_fold = Vec::new();
|
let mut to_fold = Vec::new();
|
||||||
let mut stack = vec![(0, snapshot.max_row().0, 1)];
|
let mut stack = vec![(0, snapshot.max_row().0, 1)];
|
||||||
@@ -14202,14 +14202,14 @@ impl Editor {
|
|||||||
.get("vim_mode")
|
.get("vim_mode")
|
||||||
== Some(&serde_json::Value::Bool(true));
|
== Some(&serde_json::Value::Bool(true));
|
||||||
|
|
||||||
let edit_predictions_provider = all_language_settings(file, cx).inline_completions.provider;
|
let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
|
||||||
let copilot_enabled = edit_predictions_provider
|
let copilot_enabled = edit_predictions_provider
|
||||||
== language::language_settings::InlineCompletionProvider::Copilot;
|
== language::language_settings::EditPredictionProvider::Copilot;
|
||||||
let copilot_enabled_for_language = self
|
let copilot_enabled_for_language = self
|
||||||
.buffer
|
.buffer
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.settings_at(0, cx)
|
.settings_at(0, cx)
|
||||||
.show_inline_completions;
|
.show_edit_predictions;
|
||||||
|
|
||||||
let project = project.read(cx);
|
let project = project.read(cx);
|
||||||
telemetry::event!(
|
telemetry::event!(
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub struct EditorSettings {
|
|||||||
pub auto_signature_help: bool,
|
pub auto_signature_help: bool,
|
||||||
pub show_signature_help_after_edits: bool,
|
pub show_signature_help_after_edits: bool,
|
||||||
pub jupyter: Jupyter,
|
pub jupyter: Jupyter,
|
||||||
pub show_inline_completions_in_menu: bool,
|
pub show_edit_predictions_in_menu: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||||
@@ -372,7 +372,7 @@ pub struct EditorSettingsContent {
|
|||||||
/// Only has an effect if edit prediction provider supports it.
|
/// Only has an effect if edit prediction provider supports it.
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: true
|
||||||
pub show_inline_completions_in_menu: Option<bool>,
|
pub show_edit_predictions_in_menu: Option<bool>,
|
||||||
|
|
||||||
/// Jupyter REPL settings.
|
/// Jupyter REPL settings.
|
||||||
pub jupyter: Option<JupyterContent>,
|
pub jupyter: Option<JupyterContent>,
|
||||||
|
|||||||
@@ -1159,7 +1159,7 @@ fn test_fold_at_level(cx: &mut TestAppContext) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_ = editor.update(cx, |editor, window, cx| {
|
_ = editor.update(cx, |editor, window, cx| {
|
||||||
editor.fold_at_level(&FoldAtLevel { level: 2 }, window, cx);
|
editor.fold_at_level(&FoldAtLevel(2), window, cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.display_text(cx),
|
editor.display_text(cx),
|
||||||
"
|
"
|
||||||
@@ -1183,7 +1183,7 @@ fn test_fold_at_level(cx: &mut TestAppContext) {
|
|||||||
.unindent(),
|
.unindent(),
|
||||||
);
|
);
|
||||||
|
|
||||||
editor.fold_at_level(&FoldAtLevel { level: 1 }, window, cx);
|
editor.fold_at_level(&FoldAtLevel(1), window, cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.display_text(cx),
|
editor.display_text(cx),
|
||||||
"
|
"
|
||||||
@@ -1198,7 +1198,7 @@ fn test_fold_at_level(cx: &mut TestAppContext) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
editor.unfold_all(&UnfoldAll, window, cx);
|
editor.unfold_all(&UnfoldAll, window, cx);
|
||||||
editor.fold_at_level(&FoldAtLevel { level: 0 }, window, cx);
|
editor.fold_at_level(&FoldAtLevel(0), window, cx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.display_text(cx),
|
editor.display_text(cx),
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -475,8 +475,8 @@ impl EditorElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
register_action(editor, window, Editor::show_signature_help);
|
register_action(editor, window, Editor::show_signature_help);
|
||||||
register_action(editor, window, Editor::next_inline_completion);
|
register_action(editor, window, Editor::next_edit_prediction);
|
||||||
register_action(editor, window, Editor::previous_inline_completion);
|
register_action(editor, window, Editor::previous_edit_prediction);
|
||||||
register_action(editor, window, Editor::show_inline_completion);
|
register_action(editor, window, Editor::show_inline_completion);
|
||||||
register_action(editor, window, Editor::context_menu_first);
|
register_action(editor, window, Editor::context_menu_first);
|
||||||
register_action(editor, window, Editor::context_menu_prev);
|
register_action(editor, window, Editor::context_menu_prev);
|
||||||
@@ -486,7 +486,7 @@ impl EditorElement {
|
|||||||
register_action(editor, window, Editor::unique_lines_case_insensitive);
|
register_action(editor, window, Editor::unique_lines_case_insensitive);
|
||||||
register_action(editor, window, Editor::unique_lines_case_sensitive);
|
register_action(editor, window, Editor::unique_lines_case_sensitive);
|
||||||
register_action(editor, window, Editor::accept_partial_inline_completion);
|
register_action(editor, window, Editor::accept_partial_inline_completion);
|
||||||
register_action(editor, window, Editor::accept_inline_completion);
|
register_action(editor, window, Editor::accept_edit_prediction);
|
||||||
register_action(editor, window, Editor::revert_file);
|
register_action(editor, window, Editor::revert_file);
|
||||||
register_action(editor, window, Editor::revert_selected_hunks);
|
register_action(editor, window, Editor::revert_selected_hunks);
|
||||||
register_action(editor, window, Editor::apply_all_diff_hunks);
|
register_action(editor, window, Editor::apply_all_diff_hunks);
|
||||||
@@ -3197,7 +3197,7 @@ impl EditorElement {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
// let bindings = window.bindings_for_action_in(
|
// let bindings = window.bindings_for_action_in(
|
||||||
// &crate::AcceptInlineCompletion,
|
// &crate::AcceptEditPrediction,
|
||||||
// &self.editor.focus_handle(cx),
|
// &self.editor.focus_handle(cx),
|
||||||
// );
|
// );
|
||||||
|
|
||||||
@@ -5770,7 +5770,7 @@ fn inline_completion_accept_indicator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let bindings = window.bindings_for_action_in(&crate::AcceptInlineCompletion, &focus_handle);
|
let bindings = window.bindings_for_action_in(&crate::AcceptEditPrediction, &focus_handle);
|
||||||
if let Some(keystroke) = bindings
|
if let Some(keystroke) = bindings
|
||||||
.last()
|
.last()
|
||||||
.and_then(|binding| binding.keystrokes().first())
|
.and_then(|binding| binding.keystrokes().first())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use gpui::{prelude::*, Entity};
|
use gpui::{prelude::*, Entity};
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use inline_completion::InlineCompletionProvider;
|
use inline_completion::EditPredictionProvider;
|
||||||
use language::{Language, LanguageConfig};
|
use language::{Language, LanguageConfig};
|
||||||
use multi_buffer::{Anchor, MultiBufferSnapshot, ToPoint};
|
use multi_buffer::{Anchor, MultiBufferSnapshot, ToPoint};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
@@ -315,7 +315,7 @@ fn assert_editor_active_move_completion(
|
|||||||
|
|
||||||
fn accept_completion(cx: &mut EditorTestContext) {
|
fn accept_completion(cx: &mut EditorTestContext) {
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.accept_inline_completion(&crate::AcceptInlineCompletion, window, cx)
|
editor.accept_edit_prediction(&crate::AcceptEditPrediction, window, cx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +345,7 @@ fn assign_editor_completion_provider(
|
|||||||
cx: &mut EditorTestContext,
|
cx: &mut EditorTestContext,
|
||||||
) {
|
) {
|
||||||
cx.update_editor(|editor, window, cx| {
|
cx.update_editor(|editor, window, cx| {
|
||||||
editor.set_inline_completion_provider(Some(provider), window, cx);
|
editor.set_edit_prediction_provider(Some(provider), window, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ impl FakeInlineCompletionProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineCompletionProvider for FakeInlineCompletionProvider {
|
impl EditPredictionProvider for FakeInlineCompletionProvider {
|
||||||
fn name() -> &'static str {
|
fn name() -> &'static str {
|
||||||
"fake-completion-provider"
|
"fake-completion-provider"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl DataCollectionState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait InlineCompletionProvider: 'static + Sized {
|
pub trait EditPredictionProvider: 'static + Sized {
|
||||||
fn name() -> &'static str;
|
fn name() -> &'static str;
|
||||||
fn display_name() -> &'static str;
|
fn display_name() -> &'static str;
|
||||||
fn show_completions_in_menu() -> bool;
|
fn show_completions_in_menu() -> bool;
|
||||||
@@ -126,7 +126,7 @@ pub trait InlineCompletionProviderHandle {
|
|||||||
|
|
||||||
impl<T> InlineCompletionProviderHandle for Entity<T>
|
impl<T> InlineCompletionProviderHandle for Entity<T>
|
||||||
where
|
where
|
||||||
T: InlineCompletionProvider,
|
T: EditPredictionProvider,
|
||||||
{
|
{
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
T::name()
|
T::name()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client::UserStore;
|
use client::UserStore;
|
||||||
use copilot::{Copilot, Status};
|
use copilot::{Copilot, Status};
|
||||||
use editor::{actions::ShowInlineCompletion, scroll::Autoscroll, Editor};
|
use editor::{actions::ShowEditPrediction, scroll::Autoscroll, Editor};
|
||||||
use feature_flags::{
|
use feature_flags::{
|
||||||
FeatureFlagAppExt, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
FeatureFlagAppExt, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
||||||
};
|
};
|
||||||
@@ -13,9 +13,7 @@ use gpui::{
|
|||||||
};
|
};
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use language::{
|
use language::{
|
||||||
language_settings::{
|
language_settings::{self, all_language_settings, AllLanguageSettings, EditPredictionProvider},
|
||||||
self, all_language_settings, AllLanguageSettings, InlineCompletionProvider,
|
|
||||||
},
|
|
||||||
File, Language,
|
File, Language,
|
||||||
};
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@@ -37,7 +35,7 @@ use zed_actions::OpenBrowser;
|
|||||||
use zeta::RateCompletionModal;
|
use zeta::RateCompletionModal;
|
||||||
|
|
||||||
actions!(zeta, [RateCompletions]);
|
actions!(zeta, [RateCompletions]);
|
||||||
actions!(inline_completion, [ToggleMenu]);
|
actions!(edit_prediction, [ToggleMenu]);
|
||||||
|
|
||||||
const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot";
|
const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot";
|
||||||
|
|
||||||
@@ -49,7 +47,7 @@ pub struct InlineCompletionButton {
|
|||||||
editor_focus_handle: Option<FocusHandle>,
|
editor_focus_handle: Option<FocusHandle>,
|
||||||
language: Option<Arc<Language>>,
|
language: Option<Arc<Language>>,
|
||||||
file: Option<Arc<dyn File>>,
|
file: Option<Arc<dyn File>>,
|
||||||
inline_completion_provider: Option<Arc<dyn inline_completion::InlineCompletionProviderHandle>>,
|
edit_prediction_provider: Option<Arc<dyn inline_completion::InlineCompletionProviderHandle>>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
user_store: Entity<UserStore>,
|
user_store: Entity<UserStore>,
|
||||||
@@ -67,10 +65,10 @@ impl Render for InlineCompletionButton {
|
|||||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let all_language_settings = all_language_settings(None, cx);
|
let all_language_settings = all_language_settings(None, cx);
|
||||||
|
|
||||||
match all_language_settings.inline_completions.provider {
|
match all_language_settings.edit_predictions.provider {
|
||||||
InlineCompletionProvider::None => div(),
|
EditPredictionProvider::None => div(),
|
||||||
|
|
||||||
InlineCompletionProvider::Copilot => {
|
EditPredictionProvider::Copilot => {
|
||||||
let Some(copilot) = Copilot::global(cx) else {
|
let Some(copilot) = Copilot::global(cx) else {
|
||||||
return div();
|
return div();
|
||||||
};
|
};
|
||||||
@@ -146,7 +144,7 @@ impl Render for InlineCompletionButton {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineCompletionProvider::Supermaven => {
|
EditPredictionProvider::Supermaven => {
|
||||||
let Some(supermaven) = Supermaven::global(cx) else {
|
let Some(supermaven) = Supermaven::global(cx) else {
|
||||||
return div();
|
return div();
|
||||||
};
|
};
|
||||||
@@ -196,7 +194,7 @@ impl Render for InlineCompletionButton {
|
|||||||
set_completion_provider(
|
set_completion_provider(
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
cx,
|
cx,
|
||||||
InlineCompletionProvider::Copilot,
|
EditPredictionProvider::Copilot,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -226,7 +224,7 @@ impl Render for InlineCompletionButton {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineCompletionProvider::Zed => {
|
EditPredictionProvider::Zed => {
|
||||||
if !cx.has_flag::<PredictEditsFeatureFlag>() {
|
if !cx.has_flag::<PredictEditsFeatureFlag>() {
|
||||||
return div();
|
return div();
|
||||||
}
|
}
|
||||||
@@ -307,7 +305,7 @@ impl Render for InlineCompletionButton {
|
|||||||
.with_handle(self.popover_menu_handle.clone());
|
.with_handle(self.popover_menu_handle.clone());
|
||||||
|
|
||||||
let is_refreshing = self
|
let is_refreshing = self
|
||||||
.inline_completion_provider
|
.edit_prediction_provider
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |provider| provider.is_refreshing(cx));
|
.map_or(false, |provider| provider.is_refreshing(cx));
|
||||||
|
|
||||||
@@ -352,7 +350,7 @@ impl InlineCompletionButton {
|
|||||||
editor_focus_handle: None,
|
editor_focus_handle: None,
|
||||||
language: None,
|
language: None,
|
||||||
file: None,
|
file: None,
|
||||||
inline_completion_provider: None,
|
edit_prediction_provider: None,
|
||||||
popover_menu_handle,
|
popover_menu_handle,
|
||||||
workspace,
|
workspace,
|
||||||
fs,
|
fs,
|
||||||
@@ -375,11 +373,7 @@ impl InlineCompletionButton {
|
|||||||
.entry("Use Supermaven", None, {
|
.entry("Use Supermaven", None, {
|
||||||
let fs = fs.clone();
|
let fs = fs.clone();
|
||||||
move |_window, cx| {
|
move |_window, cx| {
|
||||||
set_completion_provider(
|
set_completion_provider(fs.clone(), cx, EditPredictionProvider::Supermaven)
|
||||||
fs.clone(),
|
|
||||||
cx,
|
|
||||||
InlineCompletionProvider::Supermaven,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -394,7 +388,7 @@ impl InlineCompletionButton {
|
|||||||
let fs = fs.clone();
|
let fs = fs.clone();
|
||||||
let language_enabled =
|
let language_enabled =
|
||||||
language_settings::language_settings(Some(language.name()), None, cx)
|
language_settings::language_settings(Some(language.name()), None, cx)
|
||||||
.show_inline_completions;
|
.show_edit_predictions;
|
||||||
|
|
||||||
menu = menu.toggleable_entry(
|
menu = menu.toggleable_entry(
|
||||||
language.name(),
|
language.name(),
|
||||||
@@ -418,7 +412,7 @@ impl InlineCompletionButton {
|
|||||||
);
|
);
|
||||||
menu = menu.separator().header("Privacy Settings");
|
menu = menu.separator().header("Privacy Settings");
|
||||||
|
|
||||||
if let Some(provider) = &self.inline_completion_provider {
|
if let Some(provider) = &self.edit_prediction_provider {
|
||||||
let data_collection = provider.data_collection_state(cx);
|
let data_collection = provider.data_collection_state(cx);
|
||||||
if data_collection.is_supported() {
|
if data_collection.is_supported() {
|
||||||
let provider = provider.clone();
|
let provider = provider.clone();
|
||||||
@@ -491,12 +485,12 @@ impl InlineCompletionButton {
|
|||||||
.separator()
|
.separator()
|
||||||
.entry(
|
.entry(
|
||||||
"Predict Edit at Cursor",
|
"Predict Edit at Cursor",
|
||||||
Some(Box::new(ShowInlineCompletion)),
|
Some(Box::new(ShowEditPrediction)),
|
||||||
{
|
{
|
||||||
let editor_focus_handle = editor_focus_handle.clone();
|
let editor_focus_handle = editor_focus_handle.clone();
|
||||||
|
|
||||||
move |window, cx| {
|
move |window, cx| {
|
||||||
editor_focus_handle.dispatch_action(&ShowInlineCompletion, window, cx);
|
editor_focus_handle.dispatch_action(&ShowEditPrediction, window, cx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -579,7 +573,7 @@ impl InlineCompletionButton {
|
|||||||
.unwrap_or(true),
|
.unwrap_or(true),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.inline_completion_provider = editor.inline_completion_provider();
|
self.edit_prediction_provider = editor.edit_prediction_provider();
|
||||||
self.language = language.cloned();
|
self.language = language.cloned();
|
||||||
self.file = file;
|
self.file = file;
|
||||||
self.editor_focus_handle = Some(editor.focus_handle(cx));
|
self.editor_focus_handle = Some(editor.focus_handle(cx));
|
||||||
@@ -664,7 +658,7 @@ async fn open_disabled_globs_setting_in_editor(
|
|||||||
|
|
||||||
// Ensure that we always have "inline_completions { "disabled_globs": [] }"
|
// Ensure that we always have "inline_completions { "disabled_globs": [] }"
|
||||||
let edits = settings.edits_for_update::<AllLanguageSettings>(&text, |file| {
|
let edits = settings.edits_for_update::<AllLanguageSettings>(&text, |file| {
|
||||||
file.inline_completions
|
file.edit_predictions
|
||||||
.get_or_insert_with(Default::default)
|
.get_or_insert_with(Default::default)
|
||||||
.disabled_globs
|
.disabled_globs
|
||||||
.get_or_insert_with(Vec::new);
|
.get_or_insert_with(Vec::new);
|
||||||
@@ -696,17 +690,17 @@ async fn open_disabled_globs_setting_in_editor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_inline_completions_globally(fs: Arc<dyn Fs>, cx: &mut App) {
|
fn toggle_inline_completions_globally(fs: Arc<dyn Fs>, cx: &mut App) {
|
||||||
let show_inline_completions = all_language_settings(None, cx).show_inline_completions(None, cx);
|
let show_edit_predictions = all_language_settings(None, cx).show_inline_completions(None, cx);
|
||||||
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
||||||
file.defaults.show_inline_completions = Some(!show_inline_completions)
|
file.defaults.show_edit_predictions = Some(!show_edit_predictions)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_completion_provider(fs: Arc<dyn Fs>, cx: &mut App, provider: InlineCompletionProvider) {
|
fn set_completion_provider(fs: Arc<dyn Fs>, cx: &mut App, provider: EditPredictionProvider) {
|
||||||
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
||||||
file.features
|
file.features
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.inline_completion_provider = Some(provider);
|
.edit_prediction_provider = Some(provider);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,13 +709,13 @@ fn toggle_show_inline_completions_for_language(
|
|||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) {
|
) {
|
||||||
let show_inline_completions =
|
let show_edit_predictions =
|
||||||
all_language_settings(None, cx).show_inline_completions(Some(&language), cx);
|
all_language_settings(None, cx).show_inline_completions(Some(&language), cx);
|
||||||
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
||||||
file.languages
|
file.languages
|
||||||
.entry(language.name())
|
.entry(language.name())
|
||||||
.or_default()
|
.or_default()
|
||||||
.show_inline_completions = Some(!show_inline_completions);
|
.show_edit_predictions = Some(!show_edit_predictions);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +723,6 @@ fn hide_copilot(fs: Arc<dyn Fs>, cx: &mut App) {
|
|||||||
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
update_settings_file::<AllLanguageSettings>(fs, cx, move |file, _| {
|
||||||
file.features
|
file.features
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.inline_completion_provider = Some(InlineCompletionProvider::None);
|
.edit_prediction_provider = Some(EditPredictionProvider::None);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ pub fn all_language_settings<'a>(
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AllLanguageSettings {
|
pub struct AllLanguageSettings {
|
||||||
/// The edit prediction settings.
|
/// The edit prediction settings.
|
||||||
pub inline_completions: InlineCompletionSettings,
|
pub edit_predictions: EditPredictionSettings,
|
||||||
defaults: LanguageSettings,
|
defaults: LanguageSettings,
|
||||||
languages: HashMap<LanguageName, LanguageSettings>,
|
languages: HashMap<LanguageName, LanguageSettings>,
|
||||||
pub(crate) file_types: HashMap<Arc<str>, GlobSet>,
|
pub(crate) file_types: HashMap<Arc<str>, GlobSet>,
|
||||||
@@ -110,11 +110,11 @@ pub struct LanguageSettings {
|
|||||||
/// - `"..."` - A placeholder to refer to the **rest** of the registered language servers for this language.
|
/// - `"..."` - A placeholder to refer to the **rest** of the registered language servers for this language.
|
||||||
pub language_servers: Vec<String>,
|
pub language_servers: Vec<String>,
|
||||||
/// Controls whether edit predictions are shown immediately (true)
|
/// Controls whether edit predictions are shown immediately (true)
|
||||||
/// or manually by triggering `editor::ShowInlineCompletion` (false).
|
/// or manually by triggering `editor::ShowEditPrediction` (false).
|
||||||
pub show_inline_completions: bool,
|
pub show_edit_predictions: bool,
|
||||||
/// Controls whether edit predictions are shown in the given language
|
/// Controls whether edit predictions are shown in the given language
|
||||||
/// scopes.
|
/// scopes.
|
||||||
pub inline_completions_disabled_in: Vec<String>,
|
pub edit_predictions_disabled_in: Vec<String>,
|
||||||
/// Whether to show tabs and spaces in the editor.
|
/// Whether to show tabs and spaces in the editor.
|
||||||
pub show_whitespaces: ShowWhitespaceSetting,
|
pub show_whitespaces: ShowWhitespaceSetting,
|
||||||
/// Whether to start a new line with a comment when a previous line is a comment as well.
|
/// Whether to start a new line with a comment when a previous line is a comment as well.
|
||||||
@@ -198,7 +198,7 @@ impl LanguageSettings {
|
|||||||
/// The provider that supplies edit predictions.
|
/// The provider that supplies edit predictions.
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum InlineCompletionProvider {
|
pub enum EditPredictionProvider {
|
||||||
None,
|
None,
|
||||||
#[default]
|
#[default]
|
||||||
Copilot,
|
Copilot,
|
||||||
@@ -206,13 +206,13 @@ pub enum InlineCompletionProvider {
|
|||||||
Zed,
|
Zed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineCompletionProvider {
|
impl EditPredictionProvider {
|
||||||
pub fn is_zed(&self) -> bool {
|
pub fn is_zed(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
InlineCompletionProvider::Zed => true,
|
EditPredictionProvider::Zed => true,
|
||||||
InlineCompletionProvider::None
|
EditPredictionProvider::None
|
||||||
| InlineCompletionProvider::Copilot
|
| EditPredictionProvider::Copilot
|
||||||
| InlineCompletionProvider::Supermaven => false,
|
| EditPredictionProvider::Supermaven => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,9 +220,9 @@ impl InlineCompletionProvider {
|
|||||||
/// The settings for edit predictions, such as [GitHub Copilot](https://github.com/features/copilot)
|
/// The settings for edit predictions, such as [GitHub Copilot](https://github.com/features/copilot)
|
||||||
/// or [Supermaven](https://supermaven.com).
|
/// or [Supermaven](https://supermaven.com).
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct InlineCompletionSettings {
|
pub struct EditPredictionSettings {
|
||||||
/// The provider that supplies edit predictions.
|
/// The provider that supplies edit predictions.
|
||||||
pub provider: InlineCompletionProvider,
|
pub provider: EditPredictionProvider,
|
||||||
/// A list of globs representing files that edit predictions should be disabled for.
|
/// A list of globs representing files that edit predictions should be disabled for.
|
||||||
pub disabled_globs: Vec<GlobMatcher>,
|
pub disabled_globs: Vec<GlobMatcher>,
|
||||||
/// When to show edit predictions previews in buffer.
|
/// When to show edit predictions previews in buffer.
|
||||||
@@ -248,7 +248,7 @@ pub struct AllLanguageSettingsContent {
|
|||||||
pub features: Option<FeaturesContent>,
|
pub features: Option<FeaturesContent>,
|
||||||
/// The edit prediction settings.
|
/// The edit prediction settings.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub inline_completions: Option<InlineCompletionSettingsContent>,
|
pub edit_predictions: Option<InlineCompletionSettingsContent>,
|
||||||
/// The default language settings.
|
/// The default language settings.
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub defaults: LanguageSettingsContent,
|
pub defaults: LanguageSettingsContent,
|
||||||
@@ -347,11 +347,11 @@ pub struct LanguageSettingsContent {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub language_servers: Option<Vec<String>>,
|
pub language_servers: Option<Vec<String>>,
|
||||||
/// Controls whether edit predictions are shown immediately (true)
|
/// Controls whether edit predictions are shown immediately (true)
|
||||||
/// or manually by triggering `editor::ShowInlineCompletion` (false).
|
/// or manually by triggering `editor::ShowEditPrediction` (false).
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: true
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub show_inline_completions: Option<bool>,
|
pub show_edit_predictions: Option<bool>,
|
||||||
/// Controls whether edit predictions are shown in the given language
|
/// Controls whether edit predictions are shown in the given language
|
||||||
/// scopes.
|
/// scopes.
|
||||||
///
|
///
|
||||||
@@ -359,7 +359,7 @@ pub struct LanguageSettingsContent {
|
|||||||
///
|
///
|
||||||
/// Default: []
|
/// Default: []
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub inline_completions_disabled_in: Option<Vec<String>>,
|
pub edit_predictions_disabled_in: Option<Vec<String>>,
|
||||||
/// Whether to show tabs and spaces in the editor.
|
/// Whether to show tabs and spaces in the editor.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub show_whitespaces: Option<ShowWhitespaceSetting>,
|
pub show_whitespaces: Option<ShowWhitespaceSetting>,
|
||||||
@@ -442,7 +442,7 @@ pub struct FeaturesContent {
|
|||||||
/// Whether the GitHub Copilot feature is enabled.
|
/// Whether the GitHub Copilot feature is enabled.
|
||||||
pub copilot: Option<bool>,
|
pub copilot: Option<bool>,
|
||||||
/// Determines which edit prediction provider to use.
|
/// Determines which edit prediction provider to use.
|
||||||
pub inline_completion_provider: Option<InlineCompletionProvider>,
|
pub edit_prediction_provider: Option<EditPredictionProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Controls the soft-wrapping behavior in the editor.
|
/// Controls the soft-wrapping behavior in the editor.
|
||||||
@@ -906,7 +906,7 @@ impl AllLanguageSettings {
|
|||||||
/// Returns whether edit predictions are enabled for the given path.
|
/// Returns whether edit predictions are enabled for the given path.
|
||||||
pub fn inline_completions_enabled_for_path(&self, path: &Path) -> bool {
|
pub fn inline_completions_enabled_for_path(&self, path: &Path) -> bool {
|
||||||
!self
|
!self
|
||||||
.inline_completions
|
.edit_predictions
|
||||||
.disabled_globs
|
.disabled_globs
|
||||||
.iter()
|
.iter()
|
||||||
.any(|glob| glob.is_match(path))
|
.any(|glob| glob.is_match(path))
|
||||||
@@ -915,12 +915,12 @@ impl AllLanguageSettings {
|
|||||||
/// Returns whether edit predictions are enabled for the given language and path.
|
/// Returns whether edit predictions are enabled for the given language and path.
|
||||||
pub fn show_inline_completions(&self, language: Option<&Arc<Language>>, cx: &App) -> bool {
|
pub fn show_inline_completions(&self, language: Option<&Arc<Language>>, cx: &App) -> bool {
|
||||||
self.language(None, language.map(|l| l.name()).as_ref(), cx)
|
self.language(None, language.map(|l| l.name()).as_ref(), cx)
|
||||||
.show_inline_completions
|
.show_edit_predictions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the edit predictions preview mode for the given language and path.
|
/// Returns the edit predictions preview mode for the given language and path.
|
||||||
pub fn inline_completions_preview_mode(&self) -> InlineCompletionPreviewMode {
|
pub fn inline_completions_preview_mode(&self) -> InlineCompletionPreviewMode {
|
||||||
self.inline_completions.inline_preview
|
self.edit_predictions.inline_preview
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,18 +1015,18 @@ impl settings::Settings for AllLanguageSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut copilot_enabled = default_value.features.as_ref().and_then(|f| f.copilot);
|
let mut copilot_enabled = default_value.features.as_ref().and_then(|f| f.copilot);
|
||||||
let mut inline_completion_provider = default_value
|
let mut edit_prediction_provider = default_value
|
||||||
.features
|
.features
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|f| f.inline_completion_provider);
|
.and_then(|f| f.edit_prediction_provider);
|
||||||
let mut inline_completions_preview = default_value
|
let mut inline_completions_preview = default_value
|
||||||
.inline_completions
|
.edit_predictions
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|inline_completions| inline_completions.inline_preview)
|
.map(|inline_completions| inline_completions.inline_preview)
|
||||||
.ok_or_else(Self::missing_default)?;
|
.ok_or_else(Self::missing_default)?;
|
||||||
|
|
||||||
let mut completion_globs: HashSet<&String> = default_value
|
let mut completion_globs: HashSet<&String> = default_value
|
||||||
.inline_completions
|
.edit_predictions
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|c| c.disabled_globs.as_ref())
|
.and_then(|c| c.disabled_globs.as_ref())
|
||||||
.map(|globs| globs.iter().collect())
|
.map(|globs| globs.iter().collect())
|
||||||
@@ -1051,12 +1051,12 @@ impl settings::Settings for AllLanguageSettings {
|
|||||||
if let Some(provider) = user_settings
|
if let Some(provider) = user_settings
|
||||||
.features
|
.features
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|f| f.inline_completion_provider)
|
.and_then(|f| f.edit_prediction_provider)
|
||||||
{
|
{
|
||||||
inline_completion_provider = Some(provider);
|
edit_prediction_provider = Some(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(inline_completions) = user_settings.inline_completions.as_ref() {
|
if let Some(inline_completions) = user_settings.edit_predictions.as_ref() {
|
||||||
inline_completions_preview = inline_completions.inline_preview;
|
inline_completions_preview = inline_completions.inline_preview;
|
||||||
|
|
||||||
if let Some(disabled_globs) = inline_completions.disabled_globs.as_ref() {
|
if let Some(disabled_globs) = inline_completions.disabled_globs.as_ref() {
|
||||||
@@ -1102,13 +1102,13 @@ impl settings::Settings for AllLanguageSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inline_completions: InlineCompletionSettings {
|
edit_predictions: EditPredictionSettings {
|
||||||
provider: if let Some(provider) = inline_completion_provider {
|
provider: if let Some(provider) = edit_prediction_provider {
|
||||||
provider
|
provider
|
||||||
} else if copilot_enabled.unwrap_or(true) {
|
} else if copilot_enabled.unwrap_or(true) {
|
||||||
InlineCompletionProvider::Copilot
|
EditPredictionProvider::Copilot
|
||||||
} else {
|
} else {
|
||||||
InlineCompletionProvider::None
|
EditPredictionProvider::None
|
||||||
},
|
},
|
||||||
disabled_globs: completion_globs
|
disabled_globs: completion_globs
|
||||||
.iter()
|
.iter()
|
||||||
@@ -1219,12 +1219,12 @@ fn merge_settings(settings: &mut LanguageSettings, src: &LanguageSettingsContent
|
|||||||
);
|
);
|
||||||
merge(&mut settings.language_servers, src.language_servers.clone());
|
merge(&mut settings.language_servers, src.language_servers.clone());
|
||||||
merge(
|
merge(
|
||||||
&mut settings.show_inline_completions,
|
&mut settings.show_edit_predictions,
|
||||||
src.show_inline_completions,
|
src.show_edit_predictions,
|
||||||
);
|
);
|
||||||
merge(
|
merge(
|
||||||
&mut settings.inline_completions_disabled_in,
|
&mut settings.edit_predictions_disabled_in,
|
||||||
src.inline_completions_disabled_in.clone(),
|
src.edit_predictions_disabled_in.clone(),
|
||||||
);
|
);
|
||||||
merge(&mut settings.show_whitespaces, src.show_whitespaces);
|
merge(&mut settings.show_whitespaces, src.show_whitespaces);
|
||||||
merge(
|
merge(
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "migrator"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition.workspace = true
|
||||||
|
publish.workspace = true
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/migrator.rs"
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
collections.workspace = true
|
||||||
|
tree-sitter-json.workspace = true
|
||||||
|
tree-sitter.workspace = true
|
||||||
|
convert_case.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
pretty_assertions.workspace = true
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../LICENSE-GPL
|
||||||
@@ -0,0 +1,863 @@
|
|||||||
|
use collections::HashMap;
|
||||||
|
use convert_case::{Case, Casing};
|
||||||
|
use std::{cmp::Reverse, ops::Range, sync::LazyLock};
|
||||||
|
use tree_sitter::{Query, QueryMatch};
|
||||||
|
|
||||||
|
fn migrate(text: &str, patterns: MigrationPatterns, query: &Query) -> Option<String> {
|
||||||
|
let mut parser = tree_sitter::Parser::new();
|
||||||
|
parser
|
||||||
|
.set_language(&tree_sitter_json::LANGUAGE.into())
|
||||||
|
.unwrap();
|
||||||
|
let syntax_tree = parser.parse(&text, None).unwrap();
|
||||||
|
|
||||||
|
let mut cursor = tree_sitter::QueryCursor::new();
|
||||||
|
let matches = cursor.matches(query, syntax_tree.root_node(), text.as_bytes());
|
||||||
|
|
||||||
|
let mut edits = vec![];
|
||||||
|
for mat in matches {
|
||||||
|
if let Some((_, callback)) = patterns.get(mat.pattern_index) {
|
||||||
|
edits.extend(callback(&text, &mat, query));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edits.sort_by_key(|(range, _)| (range.start, Reverse(range.end)));
|
||||||
|
edits.dedup_by(|(range_b, _), (range_a, _)| {
|
||||||
|
range_a.contains(&range_b.start) || range_a.contains(&range_b.end)
|
||||||
|
});
|
||||||
|
|
||||||
|
if edits.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let mut text = text.to_string();
|
||||||
|
for (range, replacement) in edits.into_iter().rev() {
|
||||||
|
text.replace_range(range, &replacement);
|
||||||
|
}
|
||||||
|
Some(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migrate_keymap(text: &str) -> Option<String> {
|
||||||
|
let transformed_text = migrate(
|
||||||
|
text,
|
||||||
|
KEYMAP_MIGRATION_TRANSFORMATION_PATTERNS,
|
||||||
|
&KEYMAP_MIGRATION_TRANSFORMATION_QUERY,
|
||||||
|
);
|
||||||
|
let replacement_text = migrate(
|
||||||
|
&transformed_text.as_ref().unwrap_or(&text.to_string()),
|
||||||
|
KEYMAP_MIGRATION_REPLACEMENT_PATTERNS,
|
||||||
|
&KEYMAP_MIGRATION_REPLACEMENT_QUERY,
|
||||||
|
);
|
||||||
|
replacement_text.or(transformed_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migrate_settings(text: &str) -> Option<String> {
|
||||||
|
migrate(
|
||||||
|
&text,
|
||||||
|
SETTINGS_MIGRATION_PATTERNS,
|
||||||
|
&SETTINGS_MIGRATION_QUERY,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrationPatterns = &'static [(
|
||||||
|
&'static str,
|
||||||
|
fn(&str, &QueryMatch, &Query) -> Option<(Range<usize>, String)>,
|
||||||
|
)];
|
||||||
|
|
||||||
|
static KEYMAP_MIGRATION_TRANSFORMATION_PATTERNS: MigrationPatterns = &[
|
||||||
|
(ACTION_ARRAY_PATTERN, replace_array_with_single_string),
|
||||||
|
(
|
||||||
|
ACTION_ARGUMENT_OBJECT_PATTERN,
|
||||||
|
replace_action_argument_object_with_single_value,
|
||||||
|
),
|
||||||
|
(ACTION_STRING_PATTERN, rename_string_action),
|
||||||
|
(CONTEXT_PREDICATE_PATTERN, rename_context_key),
|
||||||
|
];
|
||||||
|
|
||||||
|
static KEYMAP_MIGRATION_TRANSFORMATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||||
|
Query::new(
|
||||||
|
&tree_sitter_json::LANGUAGE.into(),
|
||||||
|
&KEYMAP_MIGRATION_TRANSFORMATION_PATTERNS
|
||||||
|
.iter()
|
||||||
|
.map(|pattern| pattern.0)
|
||||||
|
.collect::<String>(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
const ACTION_ARRAY_PATTERN: &str = r#"(document
|
||||||
|
(array
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string)
|
||||||
|
value: ((array
|
||||||
|
. (string (string_content) @action_name)
|
||||||
|
. (string (string_content) @argument)
|
||||||
|
.)) @array
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @name "bindings")
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
fn replace_array_with_single_string(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let array_ix = query.capture_index_for_name("array").unwrap();
|
||||||
|
let action_name_ix = query.capture_index_for_name("action_name").unwrap();
|
||||||
|
let argument_ix = query.capture_index_for_name("argument").unwrap();
|
||||||
|
|
||||||
|
let action_name = contents.get(
|
||||||
|
mat.nodes_for_capture_index(action_name_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
let argument = contents.get(
|
||||||
|
mat.nodes_for_capture_index(argument_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let replacement = TRANSFORM_ARRAY.get(&(action_name, argument))?;
|
||||||
|
let replacement_as_string = format!("\"{replacement}\"");
|
||||||
|
let range_to_replace = mat.nodes_for_capture_index(array_ix).next()?.byte_range();
|
||||||
|
|
||||||
|
Some((range_to_replace, replacement_as_string))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static TRANSFORM_ARRAY: LazyLock<HashMap<(&str, &str), &str>> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
// activate
|
||||||
|
(("workspace::ActivatePaneInDirection", "Up"), "workspace::ActivatePaneUp"),
|
||||||
|
(("workspace::ActivatePaneInDirection", "Down"), "workspace::ActivatePaneDown"),
|
||||||
|
(("workspace::ActivatePaneInDirection", "Left"), "workspace::ActivatePaneLeft"),
|
||||||
|
(("workspace::ActivatePaneInDirection", "Right"), "workspace::ActivatePaneRight"),
|
||||||
|
// swap
|
||||||
|
(("workspace::SwapPaneInDirection", "Up"), "workspace::SwapPaneUp"),
|
||||||
|
(("workspace::SwapPaneInDirection", "Down"), "workspace::SwapPaneDown"),
|
||||||
|
(("workspace::SwapPaneInDirection", "Left"), "workspace::SwapPaneLeft"),
|
||||||
|
(("workspace::SwapPaneInDirection", "Right"), "workspace::SwapPaneRight"),
|
||||||
|
// menu
|
||||||
|
(("app_menu::NavigateApplicationMenuInDirection", "Left"), "app_menu::ActivateMenuLeft"),
|
||||||
|
(("app_menu::NavigateApplicationMenuInDirection", "Right"), "app_menu::ActivateMenuRight"),
|
||||||
|
// vim push
|
||||||
|
(("vim::PushOperator", "Change"), "vim::PushChange"),
|
||||||
|
(("vim::PushOperator", "Delete"), "vim::PushDelete"),
|
||||||
|
(("vim::PushOperator", "Yank"), "vim::PushYank"),
|
||||||
|
(("vim::PushOperator", "Replace"), "vim::PushReplace"),
|
||||||
|
(("vim::PushOperator", "DeleteSurrounds"), "vim::PushDeleteSurrounds"),
|
||||||
|
(("vim::PushOperator", "Mark"), "vim::PushMark"),
|
||||||
|
(("vim::PushOperator", "Indent"), "vim::PushIndent"),
|
||||||
|
(("vim::PushOperator", "Outdent"), "vim::PushOutdent"),
|
||||||
|
(("vim::PushOperator", "AutoIndent"), "vim::PushAutoIndent"),
|
||||||
|
(("vim::PushOperator", "Rewrap"), "vim::PushRewrap"),
|
||||||
|
(("vim::PushOperator", "ShellCommand"), "vim::PushShellCommand"),
|
||||||
|
(("vim::PushOperator", "Lowercase"), "vim::PushLowercase"),
|
||||||
|
(("vim::PushOperator", "Uppercase"), "vim::PushUppercase"),
|
||||||
|
(("vim::PushOperator", "OppositeCase"), "vim::PushOppositeCase"),
|
||||||
|
(("vim::PushOperator", "Register"), "vim::PushRegister"),
|
||||||
|
(("vim::PushOperator", "RecordRegister"), "vim::PushRecordRegister"),
|
||||||
|
(("vim::PushOperator", "ReplayRegister"), "vim::PushReplayRegister"),
|
||||||
|
(("vim::PushOperator", "ReplaceWithRegister"), "vim::PushReplaceWithRegister"),
|
||||||
|
(("vim::PushOperator", "ToggleComments"), "vim::PushToggleComments"),
|
||||||
|
// vim switch
|
||||||
|
(("vim::SwitchMode", "Normal"), "vim::SwitchToNormalMode"),
|
||||||
|
(("vim::SwitchMode", "Insert"), "vim::SwitchToInsertMode"),
|
||||||
|
(("vim::SwitchMode", "Replace"), "vim::SwitchToReplaceMode"),
|
||||||
|
(("vim::SwitchMode", "Visual"), "vim::SwitchToVisualMode"),
|
||||||
|
(("vim::SwitchMode", "VisualLine"), "vim::SwitchToVisualLineMode"),
|
||||||
|
(("vim::SwitchMode", "VisualBlock"), "vim::SwitchToVisualBlockMode"),
|
||||||
|
(("vim::SwitchMode", "HelixNormal"), "vim::SwitchToHelixNormalMode"),
|
||||||
|
// vim resize
|
||||||
|
(("vim::ResizePane", "Widen"), "vim::ResizePaneRight"),
|
||||||
|
(("vim::ResizePane", "Narrow"), "vim::ResizePaneLeft"),
|
||||||
|
(("vim::ResizePane", "Shorten"), "vim::ResizePaneDown"),
|
||||||
|
(("vim::ResizePane", "Lengthen"), "vim::ResizePaneUp"),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
const ACTION_ARGUMENT_OBJECT_PATTERN: &str = r#"(document
|
||||||
|
(array
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string)
|
||||||
|
value: ((array
|
||||||
|
. (string (string_content) @action_name)
|
||||||
|
. (object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @action_key)
|
||||||
|
value: (_) @argument))
|
||||||
|
. ) @array
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @name "bindings")
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
/// [ "editor::FoldAtLevel", { "level": 1 } ] -> [ "editor::FoldAtLevel", 1 ]
|
||||||
|
fn replace_action_argument_object_with_single_value(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let array_ix = query.capture_index_for_name("array").unwrap();
|
||||||
|
let action_name_ix = query.capture_index_for_name("action_name").unwrap();
|
||||||
|
let action_key_ix = query.capture_index_for_name("action_key").unwrap();
|
||||||
|
let argument_ix = query.capture_index_for_name("argument").unwrap();
|
||||||
|
|
||||||
|
let action_name = contents.get(
|
||||||
|
mat.nodes_for_capture_index(action_name_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
let action_key = contents.get(
|
||||||
|
mat.nodes_for_capture_index(action_key_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
let argument = contents.get(
|
||||||
|
mat.nodes_for_capture_index(argument_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let new_action_name = UNWRAP_OBJECTS.get(&action_name)?.get(&action_key)?;
|
||||||
|
|
||||||
|
let range_to_replace = mat.nodes_for_capture_index(array_ix).next()?.byte_range();
|
||||||
|
let replacement = format!("[\"{}\", {}]", new_action_name, argument);
|
||||||
|
Some((range_to_replace, replacement))
|
||||||
|
}
|
||||||
|
|
||||||
|
// "ctrl-k ctrl-1": [ "editor::PushOperator", { "Object": {} } ] -> [ "editor::vim::PushObject", {} ]
|
||||||
|
static UNWRAP_OBJECTS: LazyLock<HashMap<&str, HashMap<&str, &str>>> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
(
|
||||||
|
"editor::FoldAtLevel",
|
||||||
|
HashMap::from_iter([("level", "editor::FoldAtLevel")]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"vim::PushOperator",
|
||||||
|
HashMap::from_iter([
|
||||||
|
("Object", "vim::PushObject"),
|
||||||
|
("FindForward", "vim::PushFindForward"),
|
||||||
|
("FindBackward", "vim::PushFindBackward"),
|
||||||
|
("Sneak", "vim::PushSneak"),
|
||||||
|
("SneakBackward", "vim::PushSneakBackward"),
|
||||||
|
("AddSurrounds", "vim::PushAddSurrounds"),
|
||||||
|
("ChangeSurrounds", "vim::PushChangeSurrounds"),
|
||||||
|
("Jump", "vim::PushJump"),
|
||||||
|
("Digraph", "vim::PushDigraph"),
|
||||||
|
("Literal", "vim::PushLiteral"),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
static KEYMAP_MIGRATION_REPLACEMENT_PATTERNS: MigrationPatterns = &[(
|
||||||
|
ACTION_ARGUMENT_SNAKE_CASE_PATTERN,
|
||||||
|
action_argument_snake_case,
|
||||||
|
)];
|
||||||
|
|
||||||
|
static KEYMAP_MIGRATION_REPLACEMENT_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||||
|
Query::new(
|
||||||
|
&tree_sitter_json::LANGUAGE.into(),
|
||||||
|
&KEYMAP_MIGRATION_REPLACEMENT_PATTERNS
|
||||||
|
.iter()
|
||||||
|
.map(|pattern| pattern.0)
|
||||||
|
.collect::<String>(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
const ACTION_STRING_PATTERN: &str = r#"(document
|
||||||
|
(array
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string)
|
||||||
|
value: (string (string_content) @action_name)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @name "bindings")
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
fn rename_string_action(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let action_name_ix = query.capture_index_for_name("action_name").unwrap();
|
||||||
|
let action_name_range = mat
|
||||||
|
.nodes_for_capture_index(action_name_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let action_name = contents.get(action_name_range.clone())?;
|
||||||
|
let new_action_name = STRING_REPLACE.get(&action_name)?;
|
||||||
|
Some((action_name_range, new_action_name.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// "ctrl-k ctrl-1": "inline_completion::ToggleMenu" -> "edit_prediction::ToggleMenu"
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static STRING_REPLACE: LazyLock<HashMap<&str, &str>> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
("inline_completion::ToggleMenu", "edit_prediction::ToggleMenu"),
|
||||||
|
("editor::NextInlineCompletion", "editor::NextEditPrediction"),
|
||||||
|
("editor::PreviousInlineCompletion", "editor::PreviousEditPrediction"),
|
||||||
|
("editor::AcceptPartialInlineCompletion", "editor::AcceptPartialEditPrediction"),
|
||||||
|
("editor::ShowInlineCompletion", "editor::ShowEditPrediction"),
|
||||||
|
("editor::AcceptInlineCompletion", "editor::AcceptEditPrediction"),
|
||||||
|
("editor::ToggleInlineCompletions", "editor::ToggleEditPrediction"),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
const CONTEXT_PREDICATE_PATTERN: &str = r#"
|
||||||
|
(array
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (string (string_content) @context_predicate)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @name "context")
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fn rename_context_key(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let context_predicate_ix = query.capture_index_for_name("context_predicate").unwrap();
|
||||||
|
let context_predicate_range = mat
|
||||||
|
.nodes_for_capture_index(context_predicate_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let old_predicate = contents.get(context_predicate_range.clone())?.to_string();
|
||||||
|
let mut new_predicate = old_predicate.to_string();
|
||||||
|
for (old_key, new_key) in CONTEXT_REPLACE.iter() {
|
||||||
|
new_predicate = new_predicate.replace(old_key, new_key);
|
||||||
|
}
|
||||||
|
if new_predicate != old_predicate {
|
||||||
|
Some((context_predicate_range, new_predicate.to_string()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ACTION_ARGUMENT_SNAKE_CASE_PATTERN: &str = r#"(document
|
||||||
|
(array
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string)
|
||||||
|
value: ((array
|
||||||
|
. (string (string_content) @action_name)
|
||||||
|
. (object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @argument_key)
|
||||||
|
value: (_) @argument_value))
|
||||||
|
. ) @array
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @name "bindings")
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
fn is_snake_case(text: &str) -> bool {
|
||||||
|
text == text.to_case(Case::Snake)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_snake_case(text: &str) -> String {
|
||||||
|
text.to_case(Case::Snake)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [ "editor::FoldAtLevel", { "SomeKey": "Value" } ] -> [ "editor::FoldAtLevel", { "some_key" : "value" } ]
|
||||||
|
fn action_argument_snake_case(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let array_ix = query.capture_index_for_name("array").unwrap();
|
||||||
|
let action_name_ix = query.capture_index_for_name("action_name").unwrap();
|
||||||
|
let argument_key_ix = query.capture_index_for_name("argument_key").unwrap();
|
||||||
|
let argument_value_ix = query.capture_index_for_name("argument_value").unwrap();
|
||||||
|
let action_name = contents.get(
|
||||||
|
mat.nodes_for_capture_index(action_name_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let argument_key = contents.get(
|
||||||
|
mat.nodes_for_capture_index(argument_key_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let argument_value_node = mat.nodes_for_capture_index(argument_value_ix).next()?;
|
||||||
|
let argument_value = contents.get(argument_value_node.byte_range())?;
|
||||||
|
|
||||||
|
let mut needs_replacement = false;
|
||||||
|
let mut new_key = argument_key.to_string();
|
||||||
|
if !is_snake_case(argument_key) {
|
||||||
|
new_key = to_snake_case(argument_key);
|
||||||
|
needs_replacement = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_value = argument_value.to_string();
|
||||||
|
if argument_value_node.kind() == "string" {
|
||||||
|
let inner_value = argument_value.trim_matches('"');
|
||||||
|
if !is_snake_case(inner_value) {
|
||||||
|
new_value = format!("\"{}\"", to_snake_case(inner_value));
|
||||||
|
needs_replacement = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !needs_replacement {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let range_to_replace = mat.nodes_for_capture_index(array_ix).next()?.byte_range();
|
||||||
|
let replacement = format!(
|
||||||
|
"[\"{}\", {{ \"{}\": {} }}]",
|
||||||
|
action_name, new_key, new_value
|
||||||
|
);
|
||||||
|
|
||||||
|
Some((range_to_replace, replacement))
|
||||||
|
}
|
||||||
|
|
||||||
|
// "context": "Editor && inline_completion && !showing_completions" -> "Editor && edit_prediction && !showing_completions"
|
||||||
|
pub static CONTEXT_REPLACE: LazyLock<HashMap<&str, &str>> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
("inline_completion", "edit_prediction"),
|
||||||
|
(
|
||||||
|
"inline_completion_requires_modifier",
|
||||||
|
"edit_prediction_requires_modifier",
|
||||||
|
),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
static SETTINGS_MIGRATION_PATTERNS: MigrationPatterns = &[
|
||||||
|
(SETTINGS_STRING_REPLACE_QUERY, replace_setting_name),
|
||||||
|
(SETTINGS_REPLACE_NESTED_KEY, replace_setting_nested_key),
|
||||||
|
(
|
||||||
|
SETTINGS_REPLACE_IN_LANGUAGES_QUERY,
|
||||||
|
replace_setting_in_languages,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
static SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||||
|
Query::new(
|
||||||
|
&tree_sitter_json::LANGUAGE.into(),
|
||||||
|
&SETTINGS_MIGRATION_PATTERNS
|
||||||
|
.iter()
|
||||||
|
.map(|pattern| pattern.0)
|
||||||
|
.collect::<String>(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
static SETTINGS_STRING_REPLACE_QUERY: &str = r#"(document
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @name)
|
||||||
|
value: (_)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)"#;
|
||||||
|
|
||||||
|
fn replace_setting_name(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let setting_capture_ix = query.capture_index_for_name("name").unwrap();
|
||||||
|
let setting_name_range = mat
|
||||||
|
.nodes_for_capture_index(setting_capture_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let setting_name = contents.get(setting_name_range.clone())?;
|
||||||
|
let new_setting_name = SETTINGS_STRING_REPLACE.get(&setting_name)?;
|
||||||
|
Some((setting_name_range, new_setting_name.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
pub static SETTINGS_STRING_REPLACE: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
("show_inline_completions_in_menu", "show_edit_predictions_in_menu"),
|
||||||
|
("show_inline_completions", "show_edit_predictions"),
|
||||||
|
("inline_completions_disabled_in", "edit_predictions_disabled_in"),
|
||||||
|
("inline_completions", "edit_predictions")
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
static SETTINGS_REPLACE_NESTED_KEY: &str = r#"
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @parent_key)
|
||||||
|
value: (object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @setting_name)
|
||||||
|
value: (_) @value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fn replace_setting_nested_key(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let parent_object_capture_ix = query.capture_index_for_name("parent_key").unwrap();
|
||||||
|
let parent_object_range = mat
|
||||||
|
.nodes_for_capture_index(parent_object_capture_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let parent_object_name = contents.get(parent_object_range.clone())?;
|
||||||
|
|
||||||
|
let setting_name_ix = query.capture_index_for_name("setting_name").unwrap();
|
||||||
|
let setting_range = mat
|
||||||
|
.nodes_for_capture_index(setting_name_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let setting_name = contents.get(setting_range.clone())?;
|
||||||
|
|
||||||
|
let new_setting_name = SETTINGS_NESTED_STRING_REPLACE
|
||||||
|
.get(&parent_object_name)?
|
||||||
|
.get(setting_name)?;
|
||||||
|
|
||||||
|
Some((setting_range, new_setting_name.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// "features": {
|
||||||
|
// "inline_completion_provider": "copilot"
|
||||||
|
// },
|
||||||
|
pub static SETTINGS_NESTED_STRING_REPLACE: LazyLock<
|
||||||
|
HashMap<&'static str, HashMap<&'static str, &'static str>>,
|
||||||
|
> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([(
|
||||||
|
"features",
|
||||||
|
HashMap::from_iter([("inline_completion_provider", "edit_prediction_provider")]),
|
||||||
|
)])
|
||||||
|
});
|
||||||
|
|
||||||
|
static SETTINGS_REPLACE_IN_LANGUAGES_QUERY: &str = r#"
|
||||||
|
(object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @languages)
|
||||||
|
value: (object
|
||||||
|
(pair
|
||||||
|
key: (string)
|
||||||
|
value: (object
|
||||||
|
(pair
|
||||||
|
key: (string (string_content) @setting_name)
|
||||||
|
value: (_) @value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(#eq? @languages "languages")
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fn replace_setting_in_languages(
|
||||||
|
contents: &str,
|
||||||
|
mat: &QueryMatch,
|
||||||
|
query: &Query,
|
||||||
|
) -> Option<(Range<usize>, String)> {
|
||||||
|
let setting_capture_ix = query.capture_index_for_name("setting_name").unwrap();
|
||||||
|
let setting_name_range = mat
|
||||||
|
.nodes_for_capture_index(setting_capture_ix)
|
||||||
|
.next()?
|
||||||
|
.byte_range();
|
||||||
|
let setting_name = contents.get(setting_name_range.clone())?;
|
||||||
|
let new_setting_name = LANGUAGE_SETTINGS_REPLACE.get(&setting_name)?;
|
||||||
|
|
||||||
|
Some((setting_name_range, new_setting_name.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static LANGUAGE_SETTINGS_REPLACE: LazyLock<
|
||||||
|
HashMap<&'static str, &'static str>,
|
||||||
|
> = LazyLock::new(|| {
|
||||||
|
HashMap::from_iter([
|
||||||
|
("show_inline_completions", "show_edit_predictions"),
|
||||||
|
("inline_completions_disabled_in", "edit_predictions_disabled_in"),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn assert_migrate_keymap(input: &str, output: Option<&str>) {
|
||||||
|
let migrated = migrate_keymap(&input);
|
||||||
|
pretty_assertions::assert_eq!(migrated.as_deref(), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_migrate_settings(input: &str, output: Option<&str>) {
|
||||||
|
let migrated = migrate_settings(&input);
|
||||||
|
pretty_assertions::assert_eq!(migrated.as_deref(), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_array_with_single_string() {
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["workspace::ActivatePaneInDirection", "Up"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": "workspace::ActivatePaneUp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_action_argument_object_with_single_value() {
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["editor::FoldAtLevel", { "level": 1 }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["editor::FoldAtLevel", 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_action_argument_object_with_single_value_2() {
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["vim::PushOperator", { "Object": { "some" : "value" } }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["vim::PushObject", { "some" : "value" }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rename_string_action() {
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": "inline_completion::ToggleMenu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": "edit_prediction::ToggleMenu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rename_context_key() {
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"context": "Editor && inline_completion && !showing_completions"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"context": "Editor && edit_prediction && !showing_completions"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_action_argument_snake_case() {
|
||||||
|
// First performs transformations, then replacements
|
||||||
|
assert_migrate_keymap(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["vim::PushOperator", { "Object": { "SomeKey": "Value" } }],
|
||||||
|
"cmd-2": ["vim::SomeOtherAction", { "OtherKey": "Value" }],
|
||||||
|
"cmd-3": ["vim::SomeDifferentAction", { "OtherKey": true }],
|
||||||
|
"cmd-4": ["vim::OneMore", { "OtherKey": 4 }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bindings": {
|
||||||
|
"cmd-1": ["vim::PushObject", { "some_key": "value" }],
|
||||||
|
"cmd-2": ["vim::SomeOtherAction", { "other_key": "value" }],
|
||||||
|
"cmd-3": ["vim::SomeDifferentAction", { "other_key": true }],
|
||||||
|
"cmd-4": ["vim::OneMore", { "other_key": 4 }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_setting_name() {
|
||||||
|
assert_migrate_settings(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"show_inline_completions_in_menu": true,
|
||||||
|
"show_inline_completions": true,
|
||||||
|
"inline_completions_disabled_in": ["string"],
|
||||||
|
"inline_completions": { "some" : "value" }
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"show_edit_predictions_in_menu": true,
|
||||||
|
"show_edit_predictions": true,
|
||||||
|
"edit_predictions_disabled_in": ["string"],
|
||||||
|
"edit_predictions": { "some" : "value" }
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_nested_string_replace_for_settings() {
|
||||||
|
assert_migrate_settings(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"inline_completion_provider": "zed"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"edit_prediction_provider": "zed"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_settings_in_languages() {
|
||||||
|
assert_migrate_settings(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"languages": {
|
||||||
|
"Astro": {
|
||||||
|
"show_inline_completions": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
Some(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"languages": {
|
||||||
|
"Astro": {
|
||||||
|
"show_edit_predictions": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ actions!(picker, [ConfirmCompletion]);
|
|||||||
/// ConfirmInput is an alternative editor action which - instead of selecting active picker entry - treats pickers editor input literally,
|
/// ConfirmInput is an alternative editor action which - instead of selecting active picker entry - treats pickers editor input literally,
|
||||||
/// performing some kind of action on it.
|
/// performing some kind of action on it.
|
||||||
#[derive(Clone, PartialEq, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Deserialize, JsonSchema, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ConfirmInput {
|
pub struct ConfirmInput {
|
||||||
pub secondary: bool,
|
pub secondary: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,12 +162,14 @@ struct EntryDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
struct Delete {
|
struct Delete {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub skip_prompt: bool,
|
pub skip_prompt: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
struct Trash {
|
struct Trash {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub skip_prompt: bool,
|
pub skip_prompt: bool,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ use registrar::{ForDeployed, ForDismissed, SearchActionsRegistrar, WithResults};
|
|||||||
const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50;
|
const MAX_BUFFER_SEARCH_HISTORY_SIZE: usize = 50;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Deploy {
|
pub struct Deploy {
|
||||||
#[serde(default = "util::serde::default_true")]
|
#[serde(default = "util::serde::default_true")]
|
||||||
pub focus: bool,
|
pub focus: bool,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ smallvec.workspace = true
|
|||||||
tree-sitter-json.workspace = true
|
tree-sitter-json.workspace = true
|
||||||
tree-sitter.workspace = true
|
tree-sitter.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
|
migrator.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fs = { workspace = true, features = ["test-support"] }
|
fs = { workspace = true, features = ["test-support"] }
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
use std::rc::Rc;
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
|
|
||||||
use crate::{settings_store::parse_json_with_comments, SettingsAssets};
|
|
||||||
use anyhow::anyhow;
|
|
||||||
use collections::{HashMap, IndexMap};
|
use collections::{HashMap, IndexMap};
|
||||||
|
use fs::Fs;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, ActionBuildError, App, InvalidKeystrokeError, KeyBinding, KeyBindingContextPredicate,
|
Action, ActionBuildError, App, InvalidKeystrokeError, KeyBinding, KeyBindingContextPredicate,
|
||||||
NoAction, SharedString, KEYSTROKE_PARSE_EXPECTED_MESSAGE,
|
NoAction, SharedString, KEYSTROKE_PARSE_EXPECTED_MESSAGE,
|
||||||
};
|
};
|
||||||
|
use migrator::migrate_keymap;
|
||||||
use schemars::{
|
use schemars::{
|
||||||
gen::{SchemaGenerator, SchemaSettings},
|
gen::{SchemaGenerator, SchemaSettings},
|
||||||
schema::{ArrayValidation, InstanceType, Schema, SchemaObject, SubschemaValidation},
|
schema::{ArrayValidation, InstanceType, Schema, SchemaObject, SubschemaValidation},
|
||||||
JsonSchema,
|
JsonSchema,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fmt::Write;
|
use std::rc::Rc;
|
||||||
|
use std::{fmt::Write, sync::Arc};
|
||||||
use util::{asset_str, markdown::MarkdownString};
|
use util::{asset_str, markdown::MarkdownString};
|
||||||
|
|
||||||
|
use crate::{settings_store::parse_json_with_comments, SettingsAssets};
|
||||||
|
|
||||||
// Note that the doc comments on these are shown by json-language-server when editing the keymap, so
|
// Note that the doc comments on these are shown by json-language-server when editing the keymap, so
|
||||||
// they should be considered user-facing documentation. Documentation is not handled well with
|
// they should be considered user-facing documentation. Documentation is not handled well with
|
||||||
// schemars-0.8 - when there are newlines, it is rendered as plaintext (see
|
// schemars-0.8 - when there are newlines, it is rendered as plaintext (see
|
||||||
@@ -28,12 +30,12 @@ use util::{asset_str, markdown::MarkdownString};
|
|||||||
|
|
||||||
/// Keymap configuration consisting of sections. Each section may have a context predicate which
|
/// Keymap configuration consisting of sections. Each section may have a context predicate which
|
||||||
/// determines whether its bindings are used.
|
/// determines whether its bindings are used.
|
||||||
#[derive(Debug, Deserialize, Default, Clone, JsonSchema)]
|
#[derive(Debug, Deserialize, Default, Clone, JsonSchema, Serialize)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct KeymapFile(Vec<KeymapSection>);
|
pub struct KeymapFile(Vec<KeymapSection>);
|
||||||
|
|
||||||
/// Keymap section which binds keystrokes to actions.
|
/// Keymap section which binds keystrokes to actions.
|
||||||
#[derive(Debug, Deserialize, Default, Clone, JsonSchema)]
|
#[derive(Debug, Deserialize, Default, Clone, JsonSchema, Serialize)]
|
||||||
pub struct KeymapSection {
|
pub struct KeymapSection {
|
||||||
/// Determines when these bindings are active. When just a name is provided, like `Editor` or
|
/// Determines when these bindings are active. When just a name is provided, like `Editor` or
|
||||||
/// `Workspace`, the bindings will be active in that context. Boolean expressions like `X && Y`,
|
/// `Workspace`, the bindings will be active in that context. Boolean expressions like `X && Y`,
|
||||||
@@ -78,9 +80,9 @@ impl KeymapSection {
|
|||||||
/// Unlike the other json types involved in keymaps (including actions), this doc-comment will not
|
/// Unlike the other json types involved in keymaps (including actions), this doc-comment will not
|
||||||
/// be included in the generated JSON schema, as it manually defines its `JsonSchema` impl. The
|
/// be included in the generated JSON schema, as it manually defines its `JsonSchema` impl. The
|
||||||
/// actual schema used for it is automatically generated in `KeymapFile::generate_json_schema`.
|
/// actual schema used for it is automatically generated in `KeymapFile::generate_json_schema`.
|
||||||
#[derive(Debug, Deserialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Default, Clone, Serialize)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct KeymapAction(Value);
|
pub struct KeymapAction(pub(crate) Value);
|
||||||
|
|
||||||
impl std::fmt::Display for KeymapAction {
|
impl std::fmt::Display for KeymapAction {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
@@ -114,9 +116,11 @@ impl JsonSchema for KeymapAction {
|
|||||||
pub enum KeymapFileLoadResult {
|
pub enum KeymapFileLoadResult {
|
||||||
Success {
|
Success {
|
||||||
key_bindings: Vec<KeyBinding>,
|
key_bindings: Vec<KeyBinding>,
|
||||||
|
keymap_file: KeymapFile,
|
||||||
},
|
},
|
||||||
SomeFailedToLoad {
|
SomeFailedToLoad {
|
||||||
key_bindings: Vec<KeyBinding>,
|
key_bindings: Vec<KeyBinding>,
|
||||||
|
keymap_file: KeymapFile,
|
||||||
error_message: MarkdownString,
|
error_message: MarkdownString,
|
||||||
},
|
},
|
||||||
JsonParseFailure {
|
JsonParseFailure {
|
||||||
@@ -150,6 +154,7 @@ impl KeymapFile {
|
|||||||
KeymapFileLoadResult::SomeFailedToLoad {
|
KeymapFileLoadResult::SomeFailedToLoad {
|
||||||
key_bindings,
|
key_bindings,
|
||||||
error_message,
|
error_message,
|
||||||
|
..
|
||||||
} if key_bindings.is_empty() => Err(anyhow!(
|
} if key_bindings.is_empty() => Err(anyhow!(
|
||||||
"Error loading built-in keymap \"{asset_path}\": {error_message}"
|
"Error loading built-in keymap \"{asset_path}\": {error_message}"
|
||||||
)),
|
)),
|
||||||
@@ -164,7 +169,7 @@ impl KeymapFile {
|
|||||||
#[cfg(feature = "test-support")]
|
#[cfg(feature = "test-support")]
|
||||||
pub fn load_panic_on_failure(content: &str, cx: &App) -> Vec<KeyBinding> {
|
pub fn load_panic_on_failure(content: &str, cx: &App) -> Vec<KeyBinding> {
|
||||||
match Self::load(content, cx) {
|
match Self::load(content, cx) {
|
||||||
KeymapFileLoadResult::Success { key_bindings } => key_bindings,
|
KeymapFileLoadResult::Success { key_bindings, .. } => key_bindings,
|
||||||
KeymapFileLoadResult::SomeFailedToLoad { error_message, .. } => {
|
KeymapFileLoadResult::SomeFailedToLoad { error_message, .. } => {
|
||||||
panic!("{error_message}");
|
panic!("{error_message}");
|
||||||
}
|
}
|
||||||
@@ -180,6 +185,7 @@ impl KeymapFile {
|
|||||||
if content.is_empty() {
|
if content.is_empty() {
|
||||||
return KeymapFileLoadResult::Success {
|
return KeymapFileLoadResult::Success {
|
||||||
key_bindings: Vec::new(),
|
key_bindings: Vec::new(),
|
||||||
|
keymap_file: KeymapFile(Vec::new()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let keymap_file = match parse_json_with_comments::<Self>(content) {
|
let keymap_file = match parse_json_with_comments::<Self>(content) {
|
||||||
@@ -266,7 +272,10 @@ impl KeymapFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
KeymapFileLoadResult::Success { key_bindings }
|
KeymapFileLoadResult::Success {
|
||||||
|
key_bindings,
|
||||||
|
keymap_file,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut error_message = "Errors in user keymap file.\n".to_owned();
|
let mut error_message = "Errors in user keymap file.\n".to_owned();
|
||||||
for (context, section_errors) in errors {
|
for (context, section_errors) in errors {
|
||||||
@@ -284,6 +293,7 @@ impl KeymapFile {
|
|||||||
}
|
}
|
||||||
KeymapFileLoadResult::SomeFailedToLoad {
|
KeymapFileLoadResult::SomeFailedToLoad {
|
||||||
key_bindings,
|
key_bindings,
|
||||||
|
keymap_file,
|
||||||
error_message: MarkdownString(error_message),
|
error_message: MarkdownString(error_message),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -551,6 +561,55 @@ impl KeymapFile {
|
|||||||
pub fn sections(&self) -> impl DoubleEndedIterator<Item = &KeymapSection> {
|
pub fn sections(&self) -> impl DoubleEndedIterator<Item = &KeymapSection> {
|
||||||
self.0.iter()
|
self.0.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn load_keymap_file(fs: &Arc<dyn Fs>) -> Result<String> {
|
||||||
|
match fs.load(paths::keymap_file()).await {
|
||||||
|
result @ Ok(_) => result,
|
||||||
|
Err(err) => {
|
||||||
|
if let Some(e) = err.downcast_ref::<std::io::Error>() {
|
||||||
|
if e.kind() == std::io::ErrorKind::NotFound {
|
||||||
|
return Ok(crate::initial_keymap_content().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn should_migrate_keymap(keymap_file: Self) -> bool {
|
||||||
|
let Ok(old_text) = serde_json::to_string(&keymap_file) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
migrate_keymap(&old_text).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn migrate_keymap(fs: Arc<dyn Fs>) -> Result<()> {
|
||||||
|
let old_text = Self::load_keymap_file(&fs).await?;
|
||||||
|
let Some(new_text) = migrate_keymap(&old_text) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let initial_path = paths::keymap_file().as_path();
|
||||||
|
if fs.is_file(initial_path).await {
|
||||||
|
let backup_path = paths::home_dir().join(".zed_keymap_backup");
|
||||||
|
fs.atomic_write(backup_path, old_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| {
|
||||||
|
"Failed to create settings backup in home directory".to_string()
|
||||||
|
})?;
|
||||||
|
let resolved_path = fs.canonicalize(initial_path).await.with_context(|| {
|
||||||
|
format!("Failed to canonicalize keymap path {:?}", initial_path)
|
||||||
|
})?;
|
||||||
|
fs.atomic_write(resolved_path.clone(), new_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("Failed to write keymap to file {:?}", resolved_path))?;
|
||||||
|
} else {
|
||||||
|
fs.atomic_write(initial_path.to_path_buf(), new_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("Failed to write keymap to file {:?}", initial_path))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double quotes a string and wraps it in backticks for markdown inline code..
|
// Double quotes a string and wraps it in backticks for markdown inline code..
|
||||||
@@ -560,7 +619,7 @@ fn inline_code_string(text: &str) -> MarkdownString {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::KeymapFile;
|
use super::KeymapFile;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_deserialize_keymap_with_trailing_comma() {
|
fn can_deserialize_keymap_with_trailing_comma() {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ pub fn watch_config_file(
|
|||||||
pub fn handle_settings_file_changes(
|
pub fn handle_settings_file_changes(
|
||||||
mut user_settings_file_rx: mpsc::UnboundedReceiver<String>,
|
mut user_settings_file_rx: mpsc::UnboundedReceiver<String>,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
settings_changed: impl Fn(Option<anyhow::Error>, &mut App) + 'static,
|
settings_changed: impl Fn(Result<serde_json::Value, anyhow::Error>, &mut App) + 'static,
|
||||||
) {
|
) {
|
||||||
let user_settings_content = cx
|
let user_settings_content = cx
|
||||||
.background_executor()
|
.background_executor()
|
||||||
@@ -92,7 +92,7 @@ pub fn handle_settings_file_changes(
|
|||||||
if let Err(err) = &result {
|
if let Err(err) = &result {
|
||||||
log::error!("Failed to load user settings: {err}");
|
log::error!("Failed to load user settings: {err}");
|
||||||
}
|
}
|
||||||
settings_changed(result.err(), cx);
|
settings_changed(result, cx);
|
||||||
});
|
});
|
||||||
cx.spawn(move |cx| async move {
|
cx.spawn(move |cx| async move {
|
||||||
while let Some(user_settings_content) = user_settings_file_rx.next().await {
|
while let Some(user_settings_content) = user_settings_file_rx.next().await {
|
||||||
@@ -101,7 +101,7 @@ pub fn handle_settings_file_changes(
|
|||||||
if let Err(err) = &result {
|
if let Err(err) = &result {
|
||||||
log::error!("Failed to load user settings: {err}");
|
log::error!("Failed to load user settings: {err}");
|
||||||
}
|
}
|
||||||
settings_changed(result.err(), cx);
|
settings_changed(result, cx);
|
||||||
cx.refresh_windows();
|
cx.refresh_windows();
|
||||||
});
|
});
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use ec4rs::{ConfigParser, PropertiesSource, Section};
|
|||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use futures::{channel::mpsc, future::LocalBoxFuture, FutureExt, StreamExt};
|
use futures::{channel::mpsc, future::LocalBoxFuture, FutureExt, StreamExt};
|
||||||
use gpui::{App, AsyncApp, BorrowAppContext, Global, Task, UpdateGlobal};
|
use gpui::{App, AsyncApp, BorrowAppContext, Global, Task, UpdateGlobal};
|
||||||
|
use migrator::migrate_settings;
|
||||||
use paths::{local_settings_file_relative_path, EDITORCONFIG_NAME};
|
use paths::{local_settings_file_relative_path, EDITORCONFIG_NAME};
|
||||||
use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
|
use schemars::{gen::SchemaGenerator, schema::RootSchema, JsonSchema};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
@@ -17,7 +18,9 @@ use std::{
|
|||||||
sync::{Arc, LazyLock},
|
sync::{Arc, LazyLock},
|
||||||
};
|
};
|
||||||
use tree_sitter::Query;
|
use tree_sitter::Query;
|
||||||
use util::{merge_non_null_json_value_into, RangeExt, ResultExt as _};
|
use util::RangeExt;
|
||||||
|
|
||||||
|
use util::{merge_non_null_json_value_into, ResultExt as _};
|
||||||
|
|
||||||
pub type EditorconfigProperties = ec4rs::Properties;
|
pub type EditorconfigProperties = ec4rs::Properties;
|
||||||
|
|
||||||
@@ -544,7 +547,11 @@ impl SettingsStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the user settings via a JSON string.
|
/// Sets the user settings via a JSON string.
|
||||||
pub fn set_user_settings(&mut self, user_settings_content: &str, cx: &mut App) -> Result<()> {
|
pub fn set_user_settings(
|
||||||
|
&mut self,
|
||||||
|
user_settings_content: &str,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> Result<serde_json::Value> {
|
||||||
let settings: serde_json::Value = if user_settings_content.is_empty() {
|
let settings: serde_json::Value = if user_settings_content.is_empty() {
|
||||||
parse_json_with_comments("{}")?
|
parse_json_with_comments("{}")?
|
||||||
} else {
|
} else {
|
||||||
@@ -552,9 +559,9 @@ impl SettingsStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
anyhow::ensure!(settings.is_object(), "settings must be an object");
|
anyhow::ensure!(settings.is_object(), "settings must be an object");
|
||||||
self.raw_user_settings = settings;
|
self.raw_user_settings = settings.clone();
|
||||||
self.recompute_values(None, cx)?;
|
self.recompute_values(None, cx)?;
|
||||||
Ok(())
|
Ok(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_server_settings(
|
pub fn set_server_settings(
|
||||||
@@ -988,6 +995,52 @@ impl SettingsStore {
|
|||||||
properties.use_fallbacks();
|
properties.use_fallbacks();
|
||||||
Some(properties)
|
Some(properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn should_migrate_settings(settings: &serde_json::Value) -> bool {
|
||||||
|
let Ok(old_text) = serde_json::to_string(settings) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
migrate_settings(&old_text).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn migrate_settings(&self, fs: Arc<dyn Fs>) {
|
||||||
|
self.setting_file_updates_tx
|
||||||
|
.unbounded_send(Box::new(move |_: AsyncApp| {
|
||||||
|
async move {
|
||||||
|
let old_text = Self::load_settings(&fs).await?;
|
||||||
|
let Some(new_text) = migrate_settings(&old_text) else {
|
||||||
|
return anyhow::Ok(());
|
||||||
|
};
|
||||||
|
let initial_path = paths::settings_file().as_path();
|
||||||
|
if fs.is_file(initial_path).await {
|
||||||
|
let backup_path = paths::home_dir().join(".zed_settings_backup");
|
||||||
|
fs.atomic_write(backup_path, old_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| {
|
||||||
|
"Failed to create settings backup in home directory".to_string()
|
||||||
|
})?;
|
||||||
|
let resolved_path =
|
||||||
|
fs.canonicalize(initial_path).await.with_context(|| {
|
||||||
|
format!("Failed to canonicalize settings path {:?}", initial_path)
|
||||||
|
})?;
|
||||||
|
fs.atomic_write(resolved_path.clone(), new_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| {
|
||||||
|
format!("Failed to write settings to file {:?}", resolved_path)
|
||||||
|
})?;
|
||||||
|
} else {
|
||||||
|
fs.atomic_write(initial_path.to_path_buf(), new_text)
|
||||||
|
.await
|
||||||
|
.with_context(|| {
|
||||||
|
format!("Failed to write settings to file {:?}", initial_path)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
.boxed_local()
|
||||||
|
}))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@@ -1235,7 +1288,9 @@ fn replace_value_in_json_text(
|
|||||||
|
|
||||||
let found_key = text
|
let found_key = text
|
||||||
.get(key_range.clone())
|
.get(key_range.clone())
|
||||||
.map(|key_text| key_text == format!("\"{}\"", key_path[depth]))
|
.map(|key_text| {
|
||||||
|
depth < key_path.len() && key_text == format!("\"{}\"", key_path[depth])
|
||||||
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if found_key {
|
if found_key {
|
||||||
|
|||||||
@@ -31,16 +31,16 @@ pub fn init(client: Arc<Client>, cx: &mut App) {
|
|||||||
let supermaven = cx.new(|_| Supermaven::Starting);
|
let supermaven = cx.new(|_| Supermaven::Starting);
|
||||||
Supermaven::set_global(supermaven.clone(), cx);
|
Supermaven::set_global(supermaven.clone(), cx);
|
||||||
|
|
||||||
let mut provider = all_language_settings(None, cx).inline_completions.provider;
|
let mut provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
if provider == language::language_settings::InlineCompletionProvider::Supermaven {
|
if provider == language::language_settings::EditPredictionProvider::Supermaven {
|
||||||
supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
|
supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.observe_global::<SettingsStore>(move |cx| {
|
cx.observe_global::<SettingsStore>(move |cx| {
|
||||||
let new_provider = all_language_settings(None, cx).inline_completions.provider;
|
let new_provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
if new_provider != provider {
|
if new_provider != provider {
|
||||||
provider = new_provider;
|
provider = new_provider;
|
||||||
if provider == language::language_settings::InlineCompletionProvider::Supermaven {
|
if provider == language::language_settings::EditPredictionProvider::Supermaven {
|
||||||
supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
|
supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
|
||||||
} else {
|
} else {
|
||||||
supermaven.update(cx, |supermaven, _cx| supermaven.stop());
|
supermaven.update(cx, |supermaven, _cx| supermaven.stop());
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::{Supermaven, SupermavenCompletionStateId};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::StreamExt as _;
|
use futures::StreamExt as _;
|
||||||
use gpui::{App, Context, Entity, EntityId, Task};
|
use gpui::{App, Context, Entity, EntityId, Task};
|
||||||
use inline_completion::{Direction, InlineCompletion, InlineCompletionProvider};
|
use inline_completion::{Direction, EditPredictionProvider, InlineCompletion};
|
||||||
use language::{Anchor, Buffer, BufferSnapshot};
|
use language::{Anchor, Buffer, BufferSnapshot};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use std::{
|
use std::{
|
||||||
@@ -97,7 +97,7 @@ fn completion_from_diff(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineCompletionProvider for SupermavenCompletionProvider {
|
impl EditPredictionProvider for SupermavenCompletionProvider {
|
||||||
fn name() -> &'static str {
|
fn name() -> &'static str {
|
||||||
"supermaven"
|
"supermaven"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use workspace::{
|
|||||||
const PANEL_WIDTH_REMS: f32 = 28.;
|
const PANEL_WIDTH_REMS: f32 = 28.;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, JsonSchema, Default)]
|
#[derive(PartialEq, Clone, Deserialize, JsonSchema, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Toggle {
|
pub struct Toggle {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub select_last: bool,
|
pub select_last: bool,
|
||||||
|
|||||||
@@ -35,10 +35,11 @@ use workspace::{
|
|||||||
item::SerializableItem,
|
item::SerializableItem,
|
||||||
move_active_item, move_item, pane,
|
move_active_item, move_item, pane,
|
||||||
ui::IconName,
|
ui::IconName,
|
||||||
ActivateNextPane, ActivatePane, ActivatePaneInDirection, ActivatePreviousPane,
|
ActivateNextPane, ActivatePane, ActivatePaneDown, ActivatePaneLeft, ActivatePaneRight,
|
||||||
DraggedSelection, DraggedTab, ItemId, MoveItemToPane, MoveItemToPaneInDirection, NewTerminal,
|
ActivatePaneUp, ActivatePreviousPane, DraggedSelection, DraggedTab, ItemId, MoveItemToPane,
|
||||||
Pane, PaneGroup, SplitDirection, SplitDown, SplitLeft, SplitRight, SplitUp,
|
MoveItemToPaneInDirection, NewTerminal, Pane, PaneGroup, SplitDirection, SplitDown, SplitLeft,
|
||||||
SwapPaneInDirection, ToggleZoom, Workspace,
|
SplitRight, SplitUp, SwapPaneDown, SwapPaneLeft, SwapPaneRight, SwapPaneUp, ToggleZoom,
|
||||||
|
Workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
@@ -889,6 +890,37 @@ impl TerminalPanel {
|
|||||||
is_enabled_in_workspace(workspace.read(cx), cx)
|
is_enabled_in_workspace(workspace.read(cx), cx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn activate_pane_in_direction(
|
||||||
|
&mut self,
|
||||||
|
direction: SplitDirection,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
if let Some(pane) = self
|
||||||
|
.center
|
||||||
|
.find_pane_in_direction(&self.active_pane, direction, cx)
|
||||||
|
{
|
||||||
|
window.focus(&pane.focus_handle(cx));
|
||||||
|
} else {
|
||||||
|
self.workspace
|
||||||
|
.update(cx, |workspace, cx| {
|
||||||
|
workspace.activate_pane_in_direction(direction, window, cx)
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swap_pane_in_direction(&mut self, direction: SplitDirection, cx: &mut Context<Self>) {
|
||||||
|
if let Some(to) = self
|
||||||
|
.center
|
||||||
|
.find_pane_in_direction(&self.active_pane, direction, cx)
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
|
self.center.swap(&self.active_pane, &to);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_enabled_in_workspace(workspace: &Workspace, cx: &App) -> bool {
|
fn is_enabled_in_workspace(workspace: &Workspace, cx: &App) -> bool {
|
||||||
@@ -1145,24 +1177,28 @@ impl Render for TerminalPanel {
|
|||||||
.ok()
|
.ok()
|
||||||
.map(|div| {
|
.map(|div| {
|
||||||
div.on_action({
|
div.on_action({
|
||||||
cx.listener(
|
cx.listener(|terminal_panel, _: &ActivatePaneLeft, window, cx| {
|
||||||
|terminal_panel, action: &ActivatePaneInDirection, window, cx| {
|
terminal_panel.activate_pane_in_direction(SplitDirection::Left, window, cx);
|
||||||
if let Some(pane) = terminal_panel.center.find_pane_in_direction(
|
})
|
||||||
&terminal_panel.active_pane,
|
})
|
||||||
action.0,
|
.on_action({
|
||||||
cx,
|
cx.listener(|terminal_panel, _: &ActivatePaneRight, window, cx| {
|
||||||
) {
|
terminal_panel.activate_pane_in_direction(
|
||||||
window.focus(&pane.focus_handle(cx));
|
SplitDirection::Right,
|
||||||
} else {
|
window,
|
||||||
terminal_panel
|
cx,
|
||||||
.workspace
|
);
|
||||||
.update(cx, |workspace, cx| {
|
})
|
||||||
workspace.activate_pane_in_direction(action.0, window, cx)
|
})
|
||||||
})
|
.on_action({
|
||||||
.ok();
|
cx.listener(|terminal_panel, _: &ActivatePaneUp, window, cx| {
|
||||||
}
|
terminal_panel.activate_pane_in_direction(SplitDirection::Up, window, cx);
|
||||||
},
|
})
|
||||||
)
|
})
|
||||||
|
.on_action({
|
||||||
|
cx.listener(|terminal_panel, _: &ActivatePaneDown, window, cx| {
|
||||||
|
terminal_panel.activate_pane_in_direction(SplitDirection::Down, window, cx);
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.on_action(
|
.on_action(
|
||||||
cx.listener(|terminal_panel, _action: &ActivateNextPane, window, cx| {
|
cx.listener(|terminal_panel, _action: &ActivateNextPane, window, cx| {
|
||||||
@@ -1210,18 +1246,18 @@ impl Render for TerminalPanel {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.on_action(
|
.on_action(cx.listener(|terminal_panel, _: &SwapPaneLeft, _, cx| {
|
||||||
cx.listener(|terminal_panel, action: &SwapPaneInDirection, _, cx| {
|
terminal_panel.swap_pane_in_direction(SplitDirection::Left, cx);
|
||||||
if let Some(to) = terminal_panel
|
}))
|
||||||
.center
|
.on_action(cx.listener(|terminal_panel, _: &SwapPaneRight, _, cx| {
|
||||||
.find_pane_in_direction(&terminal_panel.active_pane, action.0, cx)
|
terminal_panel.swap_pane_in_direction(SplitDirection::Right, cx);
|
||||||
.cloned()
|
}))
|
||||||
{
|
.on_action(cx.listener(|terminal_panel, _: &SwapPaneUp, _, cx| {
|
||||||
terminal_panel.center.swap(&terminal_panel.active_pane, &to);
|
terminal_panel.swap_pane_in_direction(SplitDirection::Up, cx);
|
||||||
cx.notify();
|
}))
|
||||||
}
|
.on_action(cx.listener(|terminal_panel, _: &SwapPaneDown, _, cx| {
|
||||||
}),
|
terminal_panel.swap_pane_in_direction(SplitDirection::Down, cx);
|
||||||
)
|
}))
|
||||||
.on_action(
|
.on_action(
|
||||||
cx.listener(|terminal_panel, action: &MoveItemToPane, window, cx| {
|
cx.listener(|terminal_panel, action: &MoveItemToPane, window, cx| {
|
||||||
let Some(&target_pane) =
|
let Some(&target_pane) =
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
use gpui::{impl_actions, Entity, OwnedMenu, OwnedMenuItem};
|
use gpui::{Entity, OwnedMenu, OwnedMenuItem};
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
use gpui::{actions, impl_actions};
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use ui::{prelude::*, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip};
|
use ui::{prelude::*, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip};
|
||||||
|
|
||||||
impl_actions!(
|
#[cfg(not(target_os = "macos"))]
|
||||||
app_menu,
|
impl_actions!(app_menu, [OpenApplicationMenu]);
|
||||||
[OpenApplicationMenu, NavigateApplicationMenuInDirection]
|
|
||||||
);
|
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
actions!(app_menu, [ActivateMenuRight, ActivateMenuLeft]);
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq, Default)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq, Default)]
|
||||||
pub struct OpenApplicationMenu(String);
|
pub struct OpenApplicationMenu(String);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq, Default)]
|
#[cfg(not(target_os = "macos"))]
|
||||||
pub struct NavigateApplicationMenuInDirection(String);
|
pub enum ActivateDirection {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct MenuEntry {
|
struct MenuEntry {
|
||||||
@@ -190,7 +202,7 @@ impl ApplicationMenu {
|
|||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
pub fn navigate_menus_in_direction(
|
pub fn navigate_menus_in_direction(
|
||||||
&mut self,
|
&mut self,
|
||||||
action: &NavigateApplicationMenuInDirection,
|
direction: ActivateDirection,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
@@ -202,22 +214,21 @@ impl ApplicationMenu {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_index = match action.0.as_str() {
|
let next_index = match direction {
|
||||||
"Left" => {
|
ActivateDirection::Left => {
|
||||||
if current_index == 0 {
|
if current_index == 0 {
|
||||||
self.entries.len() - 1
|
self.entries.len() - 1
|
||||||
} else {
|
} else {
|
||||||
current_index - 1
|
current_index - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"Right" => {
|
ActivateDirection::Right => {
|
||||||
if current_index == self.entries.len() - 1 {
|
if current_index == self.entries.len() - 1 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
current_index + 1
|
current_index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.entries[current_index].handle.hide(cx);
|
self.entries[current_index].handle.hide(cx);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ mod stories;
|
|||||||
use crate::application_menu::ApplicationMenu;
|
use crate::application_menu::ApplicationMenu;
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
use crate::application_menu::{NavigateApplicationMenuInDirection, OpenApplicationMenu};
|
use crate::application_menu::{
|
||||||
|
ActivateDirection, ActivateMenuLeft, ActivateMenuRight, OpenApplicationMenu,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::platforms::{platform_linux, platform_mac, platform_windows};
|
use crate::platforms::{platform_linux, platform_mac, platform_windows};
|
||||||
use auto_update::AutoUpdateStatus;
|
use auto_update::AutoUpdateStatus;
|
||||||
@@ -78,22 +80,36 @@ pub fn init(cx: &mut App) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
workspace.register_action(
|
workspace.register_action(|workspace, _: &ActivateMenuRight, window, cx| {
|
||||||
|workspace, action: &NavigateApplicationMenuInDirection, window, cx| {
|
if let Some(titlebar) = workspace
|
||||||
if let Some(titlebar) = workspace
|
.titlebar_item()
|
||||||
.titlebar_item()
|
.and_then(|item| item.downcast::<TitleBar>().ok())
|
||||||
.and_then(|item| item.downcast::<TitleBar>().ok())
|
{
|
||||||
{
|
titlebar.update(cx, |titlebar, cx| {
|
||||||
titlebar.update(cx, |titlebar, cx| {
|
if let Some(ref menu) = titlebar.application_menu {
|
||||||
if let Some(ref menu) = titlebar.application_menu {
|
menu.update(cx, |menu, cx| {
|
||||||
menu.update(cx, |menu, cx| {
|
menu.navigate_menus_in_direction(ActivateDirection::Right, window, cx)
|
||||||
menu.navigate_menus_in_direction(action, window, cx)
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
);
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
workspace.register_action(|workspace, _: &ActivateMenuLeft, window, cx| {
|
||||||
|
if let Some(titlebar) = workspace
|
||||||
|
.titlebar_item()
|
||||||
|
.and_then(|item| item.downcast::<TitleBar>().ok())
|
||||||
|
{
|
||||||
|
titlebar.update(cx, |titlebar, cx| {
|
||||||
|
if let Some(ref menu) = titlebar.application_menu {
|
||||||
|
menu.update(cx, |menu, cx| {
|
||||||
|
menu.navigate_menus_in_direction(ActivateDirection::Left, window, cx)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-15
@@ -141,105 +141,105 @@ pub enum Motion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct NextWordStart {
|
struct NextWordStart {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct NextWordEnd {
|
struct NextWordEnd {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct PreviousWordStart {
|
struct PreviousWordStart {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct PreviousWordEnd {
|
struct PreviousWordEnd {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct NextSubwordStart {
|
pub(crate) struct NextSubwordStart {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) ignore_punctuation: bool,
|
pub(crate) ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct NextSubwordEnd {
|
pub(crate) struct NextSubwordEnd {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) ignore_punctuation: bool,
|
pub(crate) ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct PreviousSubwordStart {
|
pub(crate) struct PreviousSubwordStart {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) ignore_punctuation: bool,
|
pub(crate) ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct PreviousSubwordEnd {
|
pub(crate) struct PreviousSubwordEnd {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) ignore_punctuation: bool,
|
pub(crate) ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct Up {
|
pub(crate) struct Up {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) display_lines: bool,
|
pub(crate) display_lines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct Down {
|
pub(crate) struct Down {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) display_lines: bool,
|
pub(crate) display_lines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct FirstNonWhitespace {
|
struct FirstNonWhitespace {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
display_lines: bool,
|
display_lines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct EndOfLine {
|
struct EndOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
display_lines: bool,
|
display_lines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct StartOfLine {
|
pub struct StartOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub(crate) display_lines: bool,
|
pub(crate) display_lines: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct UnmatchedForward {
|
struct UnmatchedForward {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
char: char,
|
char: char,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct UnmatchedBackward {
|
struct UnmatchedBackward {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
char: char,
|
char: char,
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ use std::ops::Range;
|
|||||||
use crate::{state::Mode, Vim};
|
use crate::{state::Mode, Vim};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Increment {
|
struct Increment {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
step: bool,
|
step: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Decrement {
|
struct Decrement {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
step: bool,
|
step: bool,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Paste {
|
pub struct Paste {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
before: bool,
|
before: bool,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct MoveToNext {
|
pub(crate) struct MoveToNext {
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
case_sensitive: bool,
|
case_sensitive: bool,
|
||||||
@@ -27,7 +27,7 @@ pub(crate) struct MoveToNext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct MoveToPrev {
|
pub(crate) struct MoveToPrev {
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
case_sensitive: bool,
|
case_sensitive: bool,
|
||||||
@@ -38,6 +38,7 @@ pub(crate) struct MoveToPrev {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub(crate) struct Search {
|
pub(crate) struct Search {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
backwards: bool,
|
backwards: bool,
|
||||||
@@ -46,6 +47,7 @@ pub(crate) struct Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct FindCommand {
|
pub struct FindCommand {
|
||||||
pub query: String,
|
pub query: String,
|
||||||
pub backwards: bool,
|
pub backwards: bool,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use serde::Deserialize;
|
|||||||
use ui::Context;
|
use ui::Context;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum Object {
|
pub enum Object {
|
||||||
Word { ignore_punctuation: bool },
|
Word { ignore_punctuation: bool },
|
||||||
Subword { ignore_punctuation: bool },
|
Subword { ignore_punctuation: bool },
|
||||||
@@ -44,20 +45,20 @@ pub enum Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Word {
|
struct Word {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Subword {
|
struct Subword {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ignore_punctuation: bool,
|
ignore_punctuation: bool,
|
||||||
}
|
}
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
struct IndentObj {
|
struct IndentObj {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
include_below: bool,
|
include_below: bool,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use gpui::{
|
|||||||
Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity,
|
Action, App, BorrowAppContext, ClipboardEntry, ClipboardItem, Entity, Global, WeakEntity,
|
||||||
};
|
};
|
||||||
use language::Point;
|
use language::Point;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
@@ -18,7 +17,7 @@ use std::{fmt::Display, ops::Range, sync::Arc};
|
|||||||
use ui::{Context, SharedString};
|
use ui::{Context, SharedString};
|
||||||
use workspace::searchable::Direction;
|
use workspace::searchable::Direction;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, JsonSchema, Serialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
Normal,
|
Normal,
|
||||||
Insert,
|
Insert,
|
||||||
@@ -59,7 +58,7 @@ impl Default for Mode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
Change,
|
Change,
|
||||||
Delete,
|
Delete,
|
||||||
@@ -82,7 +81,6 @@ pub enum Operator {
|
|||||||
},
|
},
|
||||||
AddSurrounds {
|
AddSurrounds {
|
||||||
// Typically no need to configure this as `SendKeystrokes` can be used - see #23088.
|
// Typically no need to configure this as `SendKeystrokes` can be used - see #23088.
|
||||||
#[serde(skip)]
|
|
||||||
target: Option<SurroundsType>,
|
target: Option<SurroundsType>,
|
||||||
},
|
},
|
||||||
ChangeSurrounds {
|
ChangeSurrounds {
|
||||||
|
|||||||
@@ -554,11 +554,7 @@ mod test {
|
|||||||
use gpui::KeyBinding;
|
use gpui::KeyBinding;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{state::Mode, test::VimTestContext, PushAddSurrounds};
|
||||||
state::{Mode, Operator},
|
|
||||||
test::VimTestContext,
|
|
||||||
PushOperator,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_add_surrounds(cx: &mut gpui::TestAppContext) {
|
async fn test_add_surrounds(cx: &mut gpui::TestAppContext) {
|
||||||
@@ -749,7 +745,7 @@ mod test {
|
|||||||
cx.update(|_, cx| {
|
cx.update(|_, cx| {
|
||||||
cx.bind_keys([KeyBinding::new(
|
cx.bind_keys([KeyBinding::new(
|
||||||
"shift-s",
|
"shift-s",
|
||||||
PushOperator(Operator::AddSurrounds { target: None }),
|
PushAddSurrounds {},
|
||||||
Some("vim_mode == visual"),
|
Some("vim_mode == visual"),
|
||||||
)])
|
)])
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,12 +17,7 @@ use indoc::indoc;
|
|||||||
use search::BufferSearchBar;
|
use search::BufferSearchBar;
|
||||||
use workspace::WorkspaceSettings;
|
use workspace::WorkspaceSettings;
|
||||||
|
|
||||||
use crate::{
|
use crate::{insert::NormalBefore, motion, state::Mode, PushSneak, PushSneakBackward};
|
||||||
insert::NormalBefore,
|
|
||||||
motion,
|
|
||||||
state::{Mode, Operator},
|
|
||||||
PushOperator,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_initially_disabled(cx: &mut gpui::TestAppContext) {
|
async fn test_initially_disabled(cx: &mut gpui::TestAppContext) {
|
||||||
@@ -1347,17 +1342,17 @@ async fn test_sneak(cx: &mut gpui::TestAppContext) {
|
|||||||
cx.bind_keys([
|
cx.bind_keys([
|
||||||
KeyBinding::new(
|
KeyBinding::new(
|
||||||
"s",
|
"s",
|
||||||
PushOperator(Operator::Sneak { first_char: None }),
|
PushSneak { first_char: None },
|
||||||
Some("vim_mode == normal"),
|
Some("vim_mode == normal"),
|
||||||
),
|
),
|
||||||
KeyBinding::new(
|
KeyBinding::new(
|
||||||
"S",
|
"S",
|
||||||
PushOperator(Operator::SneakBackward { first_char: None }),
|
PushSneakBackward { first_char: None },
|
||||||
Some("vim_mode == normal"),
|
Some("vim_mode == normal"),
|
||||||
),
|
),
|
||||||
KeyBinding::new(
|
KeyBinding::new(
|
||||||
"S",
|
"S",
|
||||||
PushOperator(Operator::SneakBackward { first_char: None }),
|
PushSneakBackward { first_char: None },
|
||||||
Some("vim_mode == visual"),
|
Some("vim_mode == visual"),
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|||||||
+339
-35
@@ -35,6 +35,7 @@ use language::{CursorShape, Point, Selection, SelectionGoal, TransactionId};
|
|||||||
pub use mode_indicator::ModeIndicator;
|
pub use mode_indicator::ModeIndicator;
|
||||||
use motion::Motion;
|
use motion::Motion;
|
||||||
use normal::search::SearchSubmit;
|
use normal::search::SearchSubmit;
|
||||||
|
use object::Object;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
@@ -45,24 +46,10 @@ use surrounds::SurroundsType;
|
|||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
use ui::{px, IntoElement, SharedString};
|
use ui::{px, IntoElement, SharedString};
|
||||||
use vim_mode_setting::VimModeSetting;
|
use vim_mode_setting::VimModeSetting;
|
||||||
use workspace::{self, Pane, ResizeIntent, Workspace};
|
use workspace::{self, Pane, Workspace};
|
||||||
|
|
||||||
use crate::state::ReplayableAction;
|
use crate::state::ReplayableAction;
|
||||||
|
|
||||||
/// Used to resize the current pane
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
|
||||||
pub struct ResizePane(pub ResizeIntent);
|
|
||||||
|
|
||||||
/// An Action to Switch between modes
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
|
||||||
pub struct SwitchMode(pub Mode);
|
|
||||||
|
|
||||||
/// PushOperator is used to put vim into a "minor" mode,
|
|
||||||
/// where it's waiting for a specific next set of keystrokes.
|
|
||||||
/// For example 'd' needs a motion to complete.
|
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
|
||||||
pub struct PushOperator(pub Operator);
|
|
||||||
|
|
||||||
/// Number is used to manage vim's count. Pushing a digit
|
/// Number is used to manage vim's count. Pushing a digit
|
||||||
/// multiplies the current value by 10 and adds the digit.
|
/// multiplies the current value by 10 and adds the digit.
|
||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
@@ -71,29 +58,126 @@ struct Number(usize);
|
|||||||
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
struct SelectRegister(String);
|
struct SelectRegister(String);
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushObject {
|
||||||
|
around: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushFindForward {
|
||||||
|
before: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushFindBackward {
|
||||||
|
after: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushSneak {
|
||||||
|
first_char: Option<char>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushSneakBackward {
|
||||||
|
first_char: Option<char>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushAddSurrounds {}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushChangeSurrounds {
|
||||||
|
target: Option<Object>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushJump {
|
||||||
|
line: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushDigraph {
|
||||||
|
first_char: Option<char>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, JsonSchema, PartialEq)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct PushLiteral {
|
||||||
|
prefix: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
vim,
|
vim,
|
||||||
[
|
[
|
||||||
|
SwitchToNormalMode,
|
||||||
|
SwitchToInsertMode,
|
||||||
|
SwitchToReplaceMode,
|
||||||
|
SwitchToVisualMode,
|
||||||
|
SwitchToVisualLineMode,
|
||||||
|
SwitchToVisualBlockMode,
|
||||||
|
SwitchToHelixNormalMode,
|
||||||
ClearOperators,
|
ClearOperators,
|
||||||
Tab,
|
Tab,
|
||||||
Enter,
|
Enter,
|
||||||
InnerObject,
|
InnerObject,
|
||||||
FindForward,
|
|
||||||
FindBackward,
|
|
||||||
MaximizePane,
|
MaximizePane,
|
||||||
OpenDefaultKeymap,
|
OpenDefaultKeymap,
|
||||||
ResetPaneSizes,
|
ResetPaneSizes,
|
||||||
Sneak,
|
ResizePaneRight,
|
||||||
SneakBackward,
|
ResizePaneLeft,
|
||||||
|
ResizePaneUp,
|
||||||
|
ResizePaneDown,
|
||||||
|
PushChange,
|
||||||
|
PushDelete,
|
||||||
|
PushYank,
|
||||||
|
PushReplace,
|
||||||
|
PushDeleteSurrounds,
|
||||||
|
PushMark,
|
||||||
|
PushIndent,
|
||||||
|
PushOutdent,
|
||||||
|
PushAutoIndent,
|
||||||
|
PushRewrap,
|
||||||
|
PushShellCommand,
|
||||||
|
PushLowercase,
|
||||||
|
PushUppercase,
|
||||||
|
PushOppositeCase,
|
||||||
|
PushRegister,
|
||||||
|
PushRecordRegister,
|
||||||
|
PushReplayRegister,
|
||||||
|
PushReplaceWithRegister,
|
||||||
|
PushToggleComments,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// in the workspace namespace so it's not filtered out when vim is disabled.
|
// in the workspace namespace so it's not filtered out when vim is disabled.
|
||||||
actions!(workspace, [ToggleVimMode]);
|
actions!(workspace, [ToggleVimMode,]);
|
||||||
|
|
||||||
impl_actions!(
|
impl_actions!(
|
||||||
vim,
|
vim,
|
||||||
[ResizePane, SwitchMode, PushOperator, Number, SelectRegister]
|
[
|
||||||
|
Number,
|
||||||
|
SelectRegister,
|
||||||
|
PushObject,
|
||||||
|
PushFindForward,
|
||||||
|
PushFindBackward,
|
||||||
|
PushSneak,
|
||||||
|
PushSneakBackward,
|
||||||
|
PushAddSurrounds,
|
||||||
|
PushChangeSurrounds,
|
||||||
|
PushJump,
|
||||||
|
PushDigraph,
|
||||||
|
PushLiteral
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Initializes the `vim` crate.
|
/// Initializes the `vim` crate.
|
||||||
@@ -142,7 +226,7 @@ pub fn init(cx: &mut App) {
|
|||||||
workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, window, cx)
|
workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
workspace.register_action(|workspace, action: &ResizePane, window, cx| {
|
workspace.register_action(|workspace, _: &ResizePaneRight, window, cx| {
|
||||||
let count = Vim::take_count(cx).unwrap_or(1) as f32;
|
let count = Vim::take_count(cx).unwrap_or(1) as f32;
|
||||||
let theme = ThemeSettings::get_global(cx);
|
let theme = ThemeSettings::get_global(cx);
|
||||||
let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
|
let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
|
||||||
@@ -154,16 +238,36 @@ pub fn init(cx: &mut App) {
|
|||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
|
workspace.resize_pane(Axis::Horizontal, width.width * count, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
let (axis, amount) = match action.0 {
|
workspace.register_action(|workspace, _: &ResizePaneLeft, window, cx| {
|
||||||
ResizeIntent::Lengthen => (Axis::Vertical, height),
|
let count = Vim::take_count(cx).unwrap_or(1) as f32;
|
||||||
ResizeIntent::Shorten => (Axis::Vertical, height * -1.),
|
let theme = ThemeSettings::get_global(cx);
|
||||||
ResizeIntent::Widen => (Axis::Horizontal, width.width),
|
let Ok(font_id) = window.text_system().font_id(&theme.buffer_font) else {
|
||||||
ResizeIntent::Narrow => (Axis::Horizontal, width.width * -1.),
|
return;
|
||||||
};
|
};
|
||||||
|
let Ok(width) = window
|
||||||
|
.text_system()
|
||||||
|
.advance(font_id, theme.buffer_font_size(), 'm')
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
workspace.resize_pane(Axis::Horizontal, -width.width * count, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
workspace.resize_pane(axis, amount * count, window, cx);
|
workspace.register_action(|workspace, _: &ResizePaneUp, window, cx| {
|
||||||
|
let count = Vim::take_count(cx).unwrap_or(1) as f32;
|
||||||
|
let theme = ThemeSettings::get_global(cx);
|
||||||
|
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
|
||||||
|
workspace.resize_pane(Axis::Vertical, height * count, window, cx);
|
||||||
|
});
|
||||||
|
|
||||||
|
workspace.register_action(|workspace, _: &ResizePaneDown, window, cx| {
|
||||||
|
let count = Vim::take_count(cx).unwrap_or(1) as f32;
|
||||||
|
let theme = ThemeSettings::get_global(cx);
|
||||||
|
let height = theme.buffer_font_size() * theme.buffer_line_height.value();
|
||||||
|
workspace.resize_pane(Axis::Vertical, -height * count, window, cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
workspace.register_action(|workspace, _: &SearchSubmit, window, cx| {
|
workspace.register_action(|workspace, _: &SearchSubmit, window, cx| {
|
||||||
@@ -330,12 +434,212 @@ impl Vim {
|
|||||||
});
|
});
|
||||||
|
|
||||||
vim.update(cx, |_, cx| {
|
vim.update(cx, |_, cx| {
|
||||||
Vim::action(editor, cx, |vim, action: &SwitchMode, window, cx| {
|
Vim::action(editor, cx, |vim, _: &SwitchToNormalMode, window, cx| {
|
||||||
vim.switch_mode(action.0, false, window, cx)
|
vim.switch_mode(Mode::Normal, false, window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
Vim::action(editor, cx, |vim, action: &PushOperator, window, cx| {
|
Vim::action(editor, cx, |vim, _: &SwitchToInsertMode, window, cx| {
|
||||||
vim.push_operator(action.0.clone(), window, cx)
|
vim.switch_mode(Mode::Insert, false, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &SwitchToReplaceMode, window, cx| {
|
||||||
|
vim.switch_mode(Mode::Replace, false, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &SwitchToVisualMode, window, cx| {
|
||||||
|
vim.switch_mode(Mode::Visual, false, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &SwitchToVisualLineMode, window, cx| {
|
||||||
|
vim.switch_mode(Mode::VisualLine, false, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(
|
||||||
|
editor,
|
||||||
|
cx,
|
||||||
|
|vim, _: &SwitchToVisualBlockMode, window, cx| {
|
||||||
|
vim.switch_mode(Mode::VisualBlock, false, window, cx)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Vim::action(
|
||||||
|
editor,
|
||||||
|
cx,
|
||||||
|
|vim, _: &SwitchToHelixNormalMode, window, cx| {
|
||||||
|
vim.switch_mode(Mode::HelixNormal, false, window, cx)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushObject, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::Object {
|
||||||
|
around: action.around,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushFindForward, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::FindForward {
|
||||||
|
before: action.before,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushFindBackward, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::FindBackward {
|
||||||
|
after: action.after,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushSneak, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::Sneak {
|
||||||
|
first_char: action.first_char,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushSneakBackward, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::SneakBackward {
|
||||||
|
first_char: action.first_char,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushAddSurrounds, window, cx| {
|
||||||
|
vim.push_operator(Operator::AddSurrounds { target: None }, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(
|
||||||
|
editor,
|
||||||
|
cx,
|
||||||
|
|vim, action: &PushChangeSurrounds, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::ChangeSurrounds {
|
||||||
|
target: action.target,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushJump, window, cx| {
|
||||||
|
vim.push_operator(Operator::Jump { line: action.line }, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushDigraph, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::Digraph {
|
||||||
|
first_char: action.first_char,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, action: &PushLiteral, window, cx| {
|
||||||
|
vim.push_operator(
|
||||||
|
Operator::Literal {
|
||||||
|
prefix: action.prefix.clone(),
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushChange, window, cx| {
|
||||||
|
vim.push_operator(Operator::Change, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushDelete, window, cx| {
|
||||||
|
vim.push_operator(Operator::Delete, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushYank, window, cx| {
|
||||||
|
vim.push_operator(Operator::Yank, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushReplace, window, cx| {
|
||||||
|
vim.push_operator(Operator::Replace, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushDeleteSurrounds, window, cx| {
|
||||||
|
vim.push_operator(Operator::DeleteSurrounds, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushMark, window, cx| {
|
||||||
|
vim.push_operator(Operator::Mark, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushIndent, window, cx| {
|
||||||
|
vim.push_operator(Operator::Indent, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushOutdent, window, cx| {
|
||||||
|
vim.push_operator(Operator::Outdent, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushAutoIndent, window, cx| {
|
||||||
|
vim.push_operator(Operator::AutoIndent, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushRewrap, window, cx| {
|
||||||
|
vim.push_operator(Operator::Rewrap, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushShellCommand, window, cx| {
|
||||||
|
vim.push_operator(Operator::ShellCommand, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushLowercase, window, cx| {
|
||||||
|
vim.push_operator(Operator::Lowercase, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushUppercase, window, cx| {
|
||||||
|
vim.push_operator(Operator::Uppercase, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushOppositeCase, window, cx| {
|
||||||
|
vim.push_operator(Operator::OppositeCase, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushRegister, window, cx| {
|
||||||
|
vim.push_operator(Operator::Register, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushRecordRegister, window, cx| {
|
||||||
|
vim.push_operator(Operator::RecordRegister, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushReplayRegister, window, cx| {
|
||||||
|
vim.push_operator(Operator::ReplayRegister, window, cx)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vim::action(
|
||||||
|
editor,
|
||||||
|
cx,
|
||||||
|
|vim, _: &PushReplaceWithRegister, window, cx| {
|
||||||
|
vim.push_operator(Operator::ReplaceWithRegister, window, cx)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Vim::action(editor, cx, |vim, _: &PushToggleComments, window, cx| {
|
||||||
|
vim.push_operator(Operator::ToggleComments, window, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
Vim::action(editor, cx, |vim, _: &ClearOperators, window, cx| {
|
Vim::action(editor, cx, |vim, _: &ClearOperators, window, cx| {
|
||||||
@@ -1275,8 +1579,8 @@ impl Vim {
|
|||||||
|
|
||||||
if self.mode == Mode::Normal {
|
if self.mode == Mode::Normal {
|
||||||
self.update_editor(window, cx, |_, editor, window, cx| {
|
self.update_editor(window, cx, |_, editor, window, cx| {
|
||||||
editor.accept_inline_completion(
|
editor.accept_edit_prediction(
|
||||||
&editor::actions::AcceptInlineCompletion {},
|
&editor::actions::AcceptEditPrediction {},
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ impl DraggedSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)]
|
#[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum SaveIntent {
|
pub enum SaveIntent {
|
||||||
/// write all files (even if unchanged)
|
/// write all files (even if unchanged)
|
||||||
/// prompt before overwriting on-disk changes
|
/// prompt before overwriting on-disk changes
|
||||||
@@ -96,13 +96,13 @@ pub enum SaveIntent {
|
|||||||
pub struct ActivateItem(pub usize);
|
pub struct ActivateItem(pub usize);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseActiveItem {
|
pub struct CloseActiveItem {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseInactiveItems {
|
pub struct CloseInactiveItems {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -110,7 +110,7 @@ pub struct CloseInactiveItems {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseAllItems {
|
pub struct CloseAllItems {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -118,34 +118,35 @@ pub struct CloseAllItems {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseCleanItems {
|
pub struct CloseCleanItems {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub close_pinned: bool,
|
pub close_pinned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseItemsToTheRight {
|
pub struct CloseItemsToTheRight {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub close_pinned: bool,
|
pub close_pinned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseItemsToTheLeft {
|
pub struct CloseItemsToTheLeft {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub close_pinned: bool,
|
pub close_pinned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct RevealInProjectPanel {
|
pub struct RevealInProjectPanel {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub entry_id: Option<u64>,
|
pub entry_id: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct DeploySearch {
|
pub struct DeploySearch {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_enabled: bool,
|
pub replace_enabled: bool,
|
||||||
|
|||||||
@@ -725,6 +725,7 @@ impl PaneAxis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, JsonSchema)]
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, JsonSchema)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum SplitDirection {
|
pub enum SplitDirection {
|
||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
@@ -807,14 +808,6 @@ impl SplitDirection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, PartialEq)]
|
|
||||||
pub enum ResizeIntent {
|
|
||||||
Lengthen,
|
|
||||||
Shorten,
|
|
||||||
Widen,
|
|
||||||
Narrow,
|
|
||||||
}
|
|
||||||
|
|
||||||
mod element {
|
mod element {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::{cell::RefCell, iter, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, iter, rc::Rc, sync::Arc};
|
||||||
|
|||||||
@@ -170,12 +170,7 @@ pub struct OpenPaths {
|
|||||||
pub struct ActivatePane(pub usize);
|
pub struct ActivatePane(pub usize);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
||||||
pub struct ActivatePaneInDirection(pub SplitDirection);
|
#[serde(deny_unknown_fields)]
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
|
||||||
pub struct SwapPaneInDirection(pub SplitDirection);
|
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
|
||||||
pub struct MoveItemToPane {
|
pub struct MoveItemToPane {
|
||||||
pub destination: usize,
|
pub destination: usize,
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
@@ -183,6 +178,7 @@ pub struct MoveItemToPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
#[derive(Clone, Deserialize, PartialEq, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct MoveItemToPaneInDirection {
|
pub struct MoveItemToPaneInDirection {
|
||||||
pub direction: SplitDirection,
|
pub direction: SplitDirection,
|
||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
@@ -190,25 +186,25 @@ pub struct MoveItemToPaneInDirection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct SaveAll {
|
pub struct SaveAll {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Save {
|
pub struct Save {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseAllItemsAndPanes {
|
pub struct CloseAllItemsAndPanes {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CloseInactiveTabsAndPanes {
|
pub struct CloseInactiveTabsAndPanes {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
@@ -217,6 +213,7 @@ pub struct CloseInactiveTabsAndPanes {
|
|||||||
pub struct SendKeystrokes(pub String);
|
pub struct SendKeystrokes(pub String);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, Default, JsonSchema)]
|
#[derive(Clone, Deserialize, PartialEq, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Reload {
|
pub struct Reload {
|
||||||
pub binary_path: Option<PathBuf>,
|
pub binary_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
@@ -235,7 +232,6 @@ impl_actions!(
|
|||||||
workspace,
|
workspace,
|
||||||
[
|
[
|
||||||
ActivatePane,
|
ActivatePane,
|
||||||
ActivatePaneInDirection,
|
|
||||||
CloseAllItemsAndPanes,
|
CloseAllItemsAndPanes,
|
||||||
CloseInactiveTabsAndPanes,
|
CloseInactiveTabsAndPanes,
|
||||||
MoveItemToPane,
|
MoveItemToPane,
|
||||||
@@ -244,11 +240,24 @@ impl_actions!(
|
|||||||
Reload,
|
Reload,
|
||||||
Save,
|
Save,
|
||||||
SaveAll,
|
SaveAll,
|
||||||
SwapPaneInDirection,
|
|
||||||
SendKeystrokes,
|
SendKeystrokes,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
actions!(
|
||||||
|
workspace,
|
||||||
|
[
|
||||||
|
ActivatePaneLeft,
|
||||||
|
ActivatePaneRight,
|
||||||
|
ActivatePaneUp,
|
||||||
|
ActivatePaneDown,
|
||||||
|
SwapPaneLeft,
|
||||||
|
SwapPaneRight,
|
||||||
|
SwapPaneUp,
|
||||||
|
SwapPaneDown,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum CloseIntent {
|
pub enum CloseIntent {
|
||||||
/// Quit the program entirely.
|
/// Quit the program entirely.
|
||||||
@@ -301,6 +310,7 @@ impl PartialEq for Toast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, JsonSchema)]
|
#[derive(Debug, Default, Clone, Deserialize, PartialEq, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct OpenTerminal {
|
pub struct OpenTerminal {
|
||||||
pub working_directory: PathBuf,
|
pub working_directory: PathBuf,
|
||||||
}
|
}
|
||||||
@@ -4821,29 +4831,38 @@ impl Workspace {
|
|||||||
workspace.activate_previous_window(cx)
|
workspace.activate_previous_window(cx)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.on_action(
|
.on_action(cx.listener(|workspace, _: &ActivatePaneLeft, window, cx| {
|
||||||
cx.listener(|workspace, action: &ActivatePaneInDirection, window, cx| {
|
workspace.activate_pane_in_direction(SplitDirection::Left, window, cx)
|
||||||
workspace.activate_pane_in_direction(action.0, window, cx)
|
}))
|
||||||
}),
|
.on_action(cx.listener(|workspace, _: &ActivatePaneRight, window, cx| {
|
||||||
)
|
workspace.activate_pane_in_direction(SplitDirection::Right, window, cx)
|
||||||
|
}))
|
||||||
|
.on_action(cx.listener(|workspace, _: &ActivatePaneUp, window, cx| {
|
||||||
|
workspace.activate_pane_in_direction(SplitDirection::Up, window, cx)
|
||||||
|
}))
|
||||||
|
.on_action(cx.listener(|workspace, _: &ActivatePaneDown, window, cx| {
|
||||||
|
workspace.activate_pane_in_direction(SplitDirection::Down, window, cx)
|
||||||
|
}))
|
||||||
.on_action(cx.listener(|workspace, _: &ActivateNextPane, window, cx| {
|
.on_action(cx.listener(|workspace, _: &ActivateNextPane, window, cx| {
|
||||||
workspace.activate_next_pane(window, cx)
|
workspace.activate_next_pane(window, cx)
|
||||||
}))
|
}))
|
||||||
.on_action(
|
|
||||||
cx.listener(|workspace, action: &ActivatePaneInDirection, window, cx| {
|
|
||||||
workspace.activate_pane_in_direction(action.0, window, cx)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.on_action(cx.listener(
|
.on_action(cx.listener(
|
||||||
|workspace, action: &MoveItemToPaneInDirection, window, cx| {
|
|workspace, action: &MoveItemToPaneInDirection, window, cx| {
|
||||||
workspace.move_item_to_pane_in_direction(action, window, cx)
|
workspace.move_item_to_pane_in_direction(action, window, cx)
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.on_action(
|
.on_action(cx.listener(|workspace, _: &SwapPaneLeft, _, cx| {
|
||||||
cx.listener(|workspace, action: &SwapPaneInDirection, _, cx| {
|
workspace.swap_pane_in_direction(SplitDirection::Left, cx)
|
||||||
workspace.swap_pane_in_direction(action.0, cx)
|
}))
|
||||||
}),
|
.on_action(cx.listener(|workspace, _: &SwapPaneRight, _, cx| {
|
||||||
)
|
workspace.swap_pane_in_direction(SplitDirection::Right, cx)
|
||||||
|
}))
|
||||||
|
.on_action(cx.listener(|workspace, _: &SwapPaneUp, _, cx| {
|
||||||
|
workspace.swap_pane_in_direction(SplitDirection::Up, cx)
|
||||||
|
}))
|
||||||
|
.on_action(cx.listener(|workspace, _: &SwapPaneDown, _, cx| {
|
||||||
|
workspace.swap_pane_in_direction(SplitDirection::Down, cx)
|
||||||
|
}))
|
||||||
.on_action(cx.listener(|this, _: &ToggleLeftDock, window, cx| {
|
.on_action(cx.listener(|this, _: &ToggleLeftDock, window, cx| {
|
||||||
this.toggle_dock(DockPosition::Left, window, cx);
|
this.toggle_dock(DockPosition::Left, window, cx);
|
||||||
}))
|
}))
|
||||||
|
|||||||
+90
-11
@@ -20,6 +20,7 @@ use command_palette_hooks::CommandPaletteFilter;
|
|||||||
use editor::ProposedChangesEditorToolbar;
|
use editor::ProposedChangesEditorToolbar;
|
||||||
use editor::{scroll::Autoscroll, Editor, MultiBuffer};
|
use editor::{scroll::Autoscroll, Editor, MultiBuffer};
|
||||||
use feature_flags::{FeatureFlagAppExt, FeatureFlagViewExt, GitUiFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt, FeatureFlagViewExt, GitUiFeatureFlag};
|
||||||
|
use fs::Fs;
|
||||||
use futures::{channel::mpsc, select_biased, StreamExt};
|
use futures::{channel::mpsc, select_biased, StreamExt};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, point, px, Action, App, AppContext as _, AsyncApp, Context, DismissEvent, Element,
|
actions, point, px, Action, App, AppContext as _, AsyncApp, Context, DismissEvent, Element,
|
||||||
@@ -1144,18 +1145,34 @@ pub fn handle_keymap_file_changes(
|
|||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
let load_result = KeymapFile::load(&user_keymap_content, cx);
|
let load_result = KeymapFile::load(&user_keymap_content, cx);
|
||||||
match load_result {
|
match load_result {
|
||||||
KeymapFileLoadResult::Success { key_bindings } => {
|
KeymapFileLoadResult::Success {
|
||||||
|
key_bindings,
|
||||||
|
keymap_file,
|
||||||
|
} => {
|
||||||
reload_keymaps(cx, key_bindings);
|
reload_keymaps(cx, key_bindings);
|
||||||
dismiss_app_notification(¬ification_id, cx);
|
dismiss_app_notification(¬ification_id, cx);
|
||||||
|
show_keymap_migration_notification_if_needed(
|
||||||
|
keymap_file,
|
||||||
|
notification_id.clone(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
KeymapFileLoadResult::SomeFailedToLoad {
|
KeymapFileLoadResult::SomeFailedToLoad {
|
||||||
key_bindings,
|
key_bindings,
|
||||||
|
keymap_file,
|
||||||
error_message,
|
error_message,
|
||||||
} => {
|
} => {
|
||||||
if !key_bindings.is_empty() {
|
if !key_bindings.is_empty() {
|
||||||
reload_keymaps(cx, key_bindings);
|
reload_keymaps(cx, key_bindings);
|
||||||
}
|
}
|
||||||
show_keymap_file_load_error(notification_id.clone(), error_message, cx)
|
dismiss_app_notification(¬ification_id, cx);
|
||||||
|
if !show_keymap_migration_notification_if_needed(
|
||||||
|
keymap_file,
|
||||||
|
notification_id.clone(),
|
||||||
|
cx,
|
||||||
|
) {
|
||||||
|
show_keymap_file_load_error(notification_id.clone(), error_message, cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
KeymapFileLoadResult::JsonParseFailure { error } => {
|
KeymapFileLoadResult::JsonParseFailure { error } => {
|
||||||
show_keymap_file_json_error(notification_id.clone(), &error, cx)
|
show_keymap_file_json_error(notification_id.clone(), &error, cx)
|
||||||
@@ -1187,6 +1204,61 @@ fn show_keymap_file_json_error(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_keymap_migration_notification_if_needed(
|
||||||
|
keymap_file: KeymapFile,
|
||||||
|
notification_id: NotificationId,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> bool {
|
||||||
|
if !KeymapFile::should_migrate_keymap(keymap_file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
show_app_notification(notification_id, cx, move |cx| {
|
||||||
|
cx.new(move |_cx| {
|
||||||
|
let message = "A newer version of Zed has simplified several keymaps. Your existing keymaps may be deprecated. You can migrate them by clicking below. A backup will be created in your home directory.";
|
||||||
|
let button_text = "Backup and Migrate Keymap";
|
||||||
|
MessageNotification::new_from_builder(move |_, _| {
|
||||||
|
gpui::div().text_xs().child(message).into_any()
|
||||||
|
})
|
||||||
|
.primary_message(button_text)
|
||||||
|
.primary_on_click(move |_, cx| {
|
||||||
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
cx.spawn(move |weak_notification, mut cx| async move {
|
||||||
|
KeymapFile::migrate_keymap(fs).await.ok();
|
||||||
|
weak_notification.update(&mut cx, |_, cx| {
|
||||||
|
cx.emit(DismissEvent);
|
||||||
|
}).ok();
|
||||||
|
}).detach();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_settings_migration_notification_if_needed(
|
||||||
|
notification_id: NotificationId,
|
||||||
|
settings: serde_json::Value,
|
||||||
|
cx: &mut App,
|
||||||
|
) {
|
||||||
|
if !SettingsStore::should_migrate_settings(&settings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
show_app_notification(notification_id, cx, move |cx| {
|
||||||
|
cx.new(move |_cx| {
|
||||||
|
let message = "A newer version of Zed has updated some settings. Your existing settings may be deprecated. You can migrate them by clicking below. A backup will be created in your home directory.";
|
||||||
|
let button_text = "Backup and Migrate Settings";
|
||||||
|
MessageNotification::new_from_builder(move |_, _| {
|
||||||
|
gpui::div().text_xs().child(message).into_any()
|
||||||
|
})
|
||||||
|
.primary_message(button_text)
|
||||||
|
.primary_on_click(move |_, cx| {
|
||||||
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
cx.update_global(|store: &mut SettingsStore, _| store.migrate_settings(fs));
|
||||||
|
cx.emit(DismissEvent);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn show_keymap_file_load_error(
|
fn show_keymap_file_load_error(
|
||||||
notification_id: NotificationId,
|
notification_id: NotificationId,
|
||||||
markdown_error_message: MarkdownString,
|
markdown_error_message: MarkdownString,
|
||||||
@@ -1259,12 +1331,12 @@ pub fn load_default_keymap(cx: &mut App) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut App) {
|
pub fn handle_settings_changed(result: Result<serde_json::Value, anyhow::Error>, cx: &mut App) {
|
||||||
struct SettingsParseErrorNotification;
|
struct SettingsParseErrorNotification;
|
||||||
let id = NotificationId::unique::<SettingsParseErrorNotification>();
|
let id = NotificationId::unique::<SettingsParseErrorNotification>();
|
||||||
|
|
||||||
match error {
|
match result {
|
||||||
Some(error) => {
|
Err(error) => {
|
||||||
if let Some(InvalidSettingsError::LocalSettings { .. }) =
|
if let Some(InvalidSettingsError::LocalSettings { .. }) =
|
||||||
error.downcast_ref::<InvalidSettingsError>()
|
error.downcast_ref::<InvalidSettingsError>()
|
||||||
{
|
{
|
||||||
@@ -1283,7 +1355,10 @@ pub fn handle_settings_changed(error: Option<anyhow::Error>, cx: &mut App) {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => dismiss_app_notification(&id, cx),
|
Ok(settings) => {
|
||||||
|
dismiss_app_notification(&id, cx);
|
||||||
|
show_settings_migration_notification_if_needed(id, settings, cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3925,24 +4000,28 @@ mod tests {
|
|||||||
"vim::FindCommand"
|
"vim::FindCommand"
|
||||||
| "vim::Literal"
|
| "vim::Literal"
|
||||||
| "vim::ResizePane"
|
| "vim::ResizePane"
|
||||||
| "vim::SwitchMode"
|
| "vim::PushObject"
|
||||||
| "vim::PushOperator"
|
| "vim::PushFindForward"
|
||||||
|
| "vim::PushFindBackward"
|
||||||
|
| "vim::PushSneak"
|
||||||
|
| "vim::PushSneakBackward"
|
||||||
|
| "vim::PushChangeSurrounds"
|
||||||
|
| "vim::PushJump"
|
||||||
|
| "vim::PushDigraph"
|
||||||
|
| "vim::PushLiteral"
|
||||||
| "vim::Number"
|
| "vim::Number"
|
||||||
| "vim::SelectRegister"
|
| "vim::SelectRegister"
|
||||||
| "terminal::SendText"
|
| "terminal::SendText"
|
||||||
| "terminal::SendKeystroke"
|
| "terminal::SendKeystroke"
|
||||||
| "app_menu::OpenApplicationMenu"
|
| "app_menu::OpenApplicationMenu"
|
||||||
| "app_menu::NavigateApplicationMenuInDirection"
|
|
||||||
| "picker::ConfirmInput"
|
| "picker::ConfirmInput"
|
||||||
| "editor::HandleInput"
|
| "editor::HandleInput"
|
||||||
| "editor::FoldAtLevel"
|
| "editor::FoldAtLevel"
|
||||||
| "pane::ActivateItem"
|
| "pane::ActivateItem"
|
||||||
| "workspace::ActivatePane"
|
| "workspace::ActivatePane"
|
||||||
| "workspace::ActivatePaneInDirection"
|
|
||||||
| "workspace::MoveItemToPane"
|
| "workspace::MoveItemToPane"
|
||||||
| "workspace::MoveItemToPaneInDirection"
|
| "workspace::MoveItemToPaneInDirection"
|
||||||
| "workspace::OpenTerminal"
|
| "workspace::OpenTerminal"
|
||||||
| "workspace::SwapPaneInDirection"
|
|
||||||
| "workspace::SendKeystrokes"
|
| "workspace::SendKeystrokes"
|
||||||
| "zed::OpenBrowser"
|
| "zed::OpenBrowser"
|
||||||
| "zed::OpenZedUrl" => {}
|
| "zed::OpenZedUrl" => {}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use copilot::{Copilot, CopilotCompletionProvider};
|
|||||||
use editor::{Editor, EditorMode};
|
use editor::{Editor, EditorMode};
|
||||||
use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt, PredictEditsFeatureFlag};
|
||||||
use gpui::{AnyWindowHandle, App, AppContext, Context, Entity, WeakEntity};
|
use gpui::{AnyWindowHandle, App, AppContext, Context, Entity, WeakEntity};
|
||||||
use language::language_settings::{all_language_settings, InlineCompletionProvider};
|
use language::language_settings::{all_language_settings, EditPredictionProvider};
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
||||||
use supermaven::{Supermaven, SupermavenCompletionProvider};
|
use supermaven::{Supermaven, SupermavenCompletionProvider};
|
||||||
@@ -41,8 +41,8 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
editors
|
editors
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(editor_handle, window.window_handle());
|
.insert(editor_handle, window.window_handle());
|
||||||
let provider = all_language_settings(None, cx).inline_completions.provider;
|
let provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
assign_inline_completion_provider(
|
assign_edit_prediction_provider(
|
||||||
editor,
|
editor,
|
||||||
provider,
|
provider,
|
||||||
&client,
|
&client,
|
||||||
@@ -54,11 +54,11 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let mut provider = all_language_settings(None, cx).inline_completions.provider;
|
let mut provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
for (editor, window) in editors.borrow().iter() {
|
for (editor, window) in editors.borrow().iter() {
|
||||||
_ = window.update(cx, |_window, window, cx| {
|
_ = window.update(cx, |_window, window, cx| {
|
||||||
_ = editor.update(cx, |editor, cx| {
|
_ = editor.update(cx, |editor, cx| {
|
||||||
assign_inline_completion_provider(
|
assign_edit_prediction_provider(
|
||||||
editor,
|
editor,
|
||||||
provider,
|
provider,
|
||||||
&client,
|
&client,
|
||||||
@@ -79,8 +79,8 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
let user_store = user_store.clone();
|
let user_store = user_store.clone();
|
||||||
move |active, cx| {
|
move |active, cx| {
|
||||||
let provider = all_language_settings(None, cx).inline_completions.provider;
|
let provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
assign_inline_completion_providers(&editors, provider, &client, user_store.clone(), cx);
|
assign_edit_prediction_providers(&editors, provider, &client, user_store.clone(), cx);
|
||||||
if active && !cx.is_action_available(&zeta::ClearHistory) {
|
if active && !cx.is_action_available(&zeta::ClearHistory) {
|
||||||
cx.on_action(clear_zeta_edit_history);
|
cx.on_action(clear_zeta_edit_history);
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
let user_store = user_store.clone();
|
let user_store = user_store.clone();
|
||||||
move |cx| {
|
move |cx| {
|
||||||
let new_provider = all_language_settings(None, cx).inline_completions.provider;
|
let new_provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
|
|
||||||
if new_provider != provider {
|
if new_provider != provider {
|
||||||
let tos_accepted = user_store
|
let tos_accepted = user_store
|
||||||
@@ -109,7 +109,7 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
provider = new_provider;
|
provider = new_provider;
|
||||||
assign_inline_completion_providers(
|
assign_edit_prediction_providers(
|
||||||
&editors,
|
&editors,
|
||||||
provider,
|
provider,
|
||||||
&client,
|
&client,
|
||||||
@@ -119,7 +119,7 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
|
|
||||||
if !tos_accepted {
|
if !tos_accepted {
|
||||||
match provider {
|
match provider {
|
||||||
InlineCompletionProvider::Zed => {
|
EditPredictionProvider::Zed => {
|
||||||
let Some(window) = cx.active_window() else {
|
let Some(window) = cx.active_window() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -133,9 +133,9 @@ pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
InlineCompletionProvider::None
|
EditPredictionProvider::None
|
||||||
| InlineCompletionProvider::Copilot
|
| EditPredictionProvider::Copilot
|
||||||
| InlineCompletionProvider::Supermaven => {}
|
| EditPredictionProvider::Supermaven => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,9 +150,9 @@ fn clear_zeta_edit_history(_: &zeta::ClearHistory, cx: &mut App) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_inline_completion_providers(
|
fn assign_edit_prediction_providers(
|
||||||
editors: &Rc<RefCell<HashMap<WeakEntity<Editor>, AnyWindowHandle>>>,
|
editors: &Rc<RefCell<HashMap<WeakEntity<Editor>, AnyWindowHandle>>>,
|
||||||
provider: InlineCompletionProvider,
|
provider: EditPredictionProvider,
|
||||||
client: &Arc<Client>,
|
client: &Arc<Client>,
|
||||||
user_store: Entity<UserStore>,
|
user_store: Entity<UserStore>,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
@@ -160,7 +160,7 @@ fn assign_inline_completion_providers(
|
|||||||
for (editor, window) in editors.borrow().iter() {
|
for (editor, window) in editors.borrow().iter() {
|
||||||
_ = window.update(cx, |_window, window, cx| {
|
_ = window.update(cx, |_window, window, cx| {
|
||||||
_ = editor.update(cx, |editor, cx| {
|
_ = editor.update(cx, |editor, cx| {
|
||||||
assign_inline_completion_provider(
|
assign_edit_prediction_provider(
|
||||||
editor,
|
editor,
|
||||||
provider,
|
provider,
|
||||||
&client,
|
&client,
|
||||||
@@ -187,7 +187,7 @@ fn register_backward_compatible_actions(editor: &mut Editor, cx: &mut Context<Ed
|
|||||||
editor
|
editor
|
||||||
.register_action(cx.listener(
|
.register_action(cx.listener(
|
||||||
|editor, _: &copilot::NextSuggestion, window: &mut Window, cx: &mut Context<Editor>| {
|
|editor, _: &copilot::NextSuggestion, window: &mut Window, cx: &mut Context<Editor>| {
|
||||||
editor.next_inline_completion(&Default::default(), window, cx);
|
editor.next_edit_prediction(&Default::default(), window, cx);
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.detach();
|
.detach();
|
||||||
@@ -197,7 +197,7 @@ fn register_backward_compatible_actions(editor: &mut Editor, cx: &mut Context<Ed
|
|||||||
_: &copilot::PreviousSuggestion,
|
_: &copilot::PreviousSuggestion,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Editor>| {
|
cx: &mut Context<Editor>| {
|
||||||
editor.previous_inline_completion(&Default::default(), window, cx);
|
editor.previous_edit_prediction(&Default::default(), window, cx);
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.detach();
|
.detach();
|
||||||
@@ -213,9 +213,9 @@ fn register_backward_compatible_actions(editor: &mut Editor, cx: &mut Context<Ed
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_inline_completion_provider(
|
fn assign_edit_prediction_provider(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
provider: InlineCompletionProvider,
|
provider: EditPredictionProvider,
|
||||||
client: &Arc<Client>,
|
client: &Arc<Client>,
|
||||||
user_store: Entity<UserStore>,
|
user_store: Entity<UserStore>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
@@ -225,8 +225,8 @@ fn assign_inline_completion_provider(
|
|||||||
let singleton_buffer = editor.buffer().read(cx).as_singleton();
|
let singleton_buffer = editor.buffer().read(cx).as_singleton();
|
||||||
|
|
||||||
match provider {
|
match provider {
|
||||||
InlineCompletionProvider::None => {}
|
EditPredictionProvider::None => {}
|
||||||
InlineCompletionProvider::Copilot => {
|
EditPredictionProvider::Copilot => {
|
||||||
if let Some(copilot) = Copilot::global(cx) {
|
if let Some(copilot) = Copilot::global(cx) {
|
||||||
if let Some(buffer) = singleton_buffer {
|
if let Some(buffer) = singleton_buffer {
|
||||||
if buffer.read(cx).file().is_some() {
|
if buffer.read(cx).file().is_some() {
|
||||||
@@ -236,16 +236,16 @@ fn assign_inline_completion_provider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
let provider = cx.new(|_| CopilotCompletionProvider::new(copilot));
|
||||||
editor.set_inline_completion_provider(Some(provider), window, cx);
|
editor.set_edit_prediction_provider(Some(provider), window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineCompletionProvider::Supermaven => {
|
EditPredictionProvider::Supermaven => {
|
||||||
if let Some(supermaven) = Supermaven::global(cx) {
|
if let Some(supermaven) = Supermaven::global(cx) {
|
||||||
let provider = cx.new(|_| SupermavenCompletionProvider::new(supermaven));
|
let provider = cx.new(|_| SupermavenCompletionProvider::new(supermaven));
|
||||||
editor.set_inline_completion_provider(Some(provider), window, cx);
|
editor.set_edit_prediction_provider(Some(provider), window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineCompletionProvider::Zed => {
|
EditPredictionProvider::Zed => {
|
||||||
if cx.has_flag::<PredictEditsFeatureFlag>()
|
if cx.has_flag::<PredictEditsFeatureFlag>()
|
||||||
|| (cfg!(debug_assertions) && client.status().borrow().is_connected())
|
|| (cfg!(debug_assertions) && client.status().borrow().is_connected())
|
||||||
{
|
{
|
||||||
@@ -280,7 +280,7 @@ fn assign_inline_completion_provider(
|
|||||||
let provider =
|
let provider =
|
||||||
cx.new(|_| zeta::ZetaInlineCompletionProvider::new(zeta, data_collection));
|
cx.new(|_| zeta::ZetaInlineCompletionProvider::new(zeta, data_collection));
|
||||||
|
|
||||||
editor.set_inline_completion_provider(Some(provider), window, cx);
|
editor.set_edit_prediction_provider(Some(provider), window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,14 +301,14 @@ impl Render for QuickActionBar {
|
|||||||
.toggleable(IconPosition::Start, inline_completion_enabled && show_inline_completions)
|
.toggleable(IconPosition::Start, inline_completion_enabled && show_inline_completions)
|
||||||
.disabled(!inline_completion_enabled)
|
.disabled(!inline_completion_enabled)
|
||||||
.action(Some(
|
.action(Some(
|
||||||
editor::actions::ToggleInlineCompletions.boxed_clone(),
|
editor::actions::ToggleEditPrediction.boxed_clone(),
|
||||||
)).handler({
|
)).handler({
|
||||||
let editor = editor.clone();
|
let editor = editor.clone();
|
||||||
move |window, cx| {
|
move |window, cx| {
|
||||||
editor
|
editor
|
||||||
.update(cx, |editor, cx| {
|
.update(cx, |editor, cx| {
|
||||||
editor.toggle_inline_completions(
|
editor.toggle_inline_completions(
|
||||||
&editor::actions::ToggleInlineCompletions,
|
&editor::actions::ToggleEditPrediction,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub fn init() {}
|
pub fn init() {}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Deserialize, JsonSchema)]
|
#[derive(Clone, PartialEq, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct OpenBrowser {
|
pub struct OpenBrowser {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Deserialize, JsonSchema)]
|
#[derive(Clone, PartialEq, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct OpenZedUrl {
|
pub struct OpenZedUrl {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
@@ -69,6 +71,7 @@ pub mod theme_selector {
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Toggle {
|
pub struct Toggle {
|
||||||
/// A list of theme names to filter the theme selector down to.
|
/// A list of theme names to filter the theme selector down to.
|
||||||
pub themes_filter: Option<Vec<String>>,
|
pub themes_filter: Option<Vec<String>>,
|
||||||
@@ -83,6 +86,7 @@ pub mod icon_theme_selector {
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Toggle {
|
pub struct Toggle {
|
||||||
/// A list of icon theme names to filter the theme selector down to.
|
/// A list of icon theme names to filter the theme selector down to.
|
||||||
pub themes_filter: Option<Vec<String>>,
|
pub themes_filter: Option<Vec<String>>,
|
||||||
@@ -99,6 +103,7 @@ pub mod assistant {
|
|||||||
actions!(assistant, [ToggleFocus, DeployPromptLibrary]);
|
actions!(assistant, [ToggleFocus, DeployPromptLibrary]);
|
||||||
|
|
||||||
#[derive(Clone, Default, Deserialize, PartialEq, JsonSchema)]
|
#[derive(Clone, Default, Deserialize, PartialEq, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct InlineAssist {
|
pub struct InlineAssist {
|
||||||
pub prompt: Option<String>,
|
pub prompt: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -107,6 +112,7 @@ pub mod assistant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct OpenRecent {
|
pub struct OpenRecent {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub create_new_window: bool,
|
pub create_new_window: bool,
|
||||||
@@ -154,6 +160,7 @@ impl Spawn {
|
|||||||
|
|
||||||
/// Rerun the last task.
|
/// Rerun the last task.
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct Rerun {
|
pub struct Rerun {
|
||||||
/// Controls whether the task context is reevaluated prior to execution of a task.
|
/// Controls whether the task context is reevaluated prior to execution of a task.
|
||||||
/// If it is not, environment variables such as ZED_COLUMN, ZED_FILE are gonna be the same as in the last execution of a task
|
/// If it is not, environment variables such as ZED_COLUMN, ZED_FILE are gonna be the same as in the last execution of a task
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use feature_flags::{
|
|||||||
FeatureFlagAppExt as _, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
FeatureFlagAppExt as _, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag,
|
||||||
};
|
};
|
||||||
use gpui::actions;
|
use gpui::actions;
|
||||||
use language::language_settings::{AllLanguageSettings, InlineCompletionProvider};
|
use language::language_settings::{AllLanguageSettings, EditPredictionProvider};
|
||||||
use settings::update_settings_file;
|
use settings::update_settings_file;
|
||||||
use ui::App;
|
use ui::App;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
@@ -44,7 +44,7 @@ pub fn init(cx: &mut App) {
|
|||||||
move |file, _| {
|
move |file, _| {
|
||||||
file.features
|
file.features
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.inline_completion_provider = Some(InlineCompletionProvider::None)
|
.edit_prediction_provider = Some(EditPredictionProvider::None)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use feature_flags::{FeatureFlagAppExt as _, PredictEditsFeatureFlag};
|
use feature_flags::{FeatureFlagAppExt as _, PredictEditsFeatureFlag};
|
||||||
use gpui::Subscription;
|
use gpui::Subscription;
|
||||||
use language::language_settings::{all_language_settings, InlineCompletionProvider};
|
use language::language_settings::{all_language_settings, EditPredictionProvider};
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
use ui::{prelude::*, ButtonLike, Tooltip};
|
use ui::{prelude::*, ButtonLike, Tooltip};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
@@ -11,7 +11,7 @@ use crate::onboarding_event;
|
|||||||
/// Prompts the user to try Zed's Edit Prediction feature
|
/// Prompts the user to try Zed's Edit Prediction feature
|
||||||
pub struct ZedPredictBanner {
|
pub struct ZedPredictBanner {
|
||||||
dismissed: bool,
|
dismissed: bool,
|
||||||
provider: InlineCompletionProvider,
|
provider: EditPredictionProvider,
|
||||||
_subscription: Subscription,
|
_subscription: Subscription,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ impl ZedPredictBanner {
|
|||||||
pub fn new(cx: &mut Context<Self>) -> Self {
|
pub fn new(cx: &mut Context<Self>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dismissed: get_dismissed(),
|
dismissed: get_dismissed(),
|
||||||
provider: all_language_settings(None, cx).inline_completions.provider,
|
provider: all_language_settings(None, cx).edit_predictions.provider,
|
||||||
_subscription: cx.observe_global::<SettingsStore>(Self::handle_settings_changed),
|
_subscription: cx.observe_global::<SettingsStore>(Self::handle_settings_changed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ impl ZedPredictBanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_settings_changed(&mut self, cx: &mut Context<Self>) {
|
fn handle_settings_changed(&mut self, cx: &mut Context<Self>) {
|
||||||
let new_provider = all_language_settings(None, cx).inline_completions.provider;
|
let new_provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||||
|
|
||||||
if new_provider == self.provider {
|
if new_provider == self.provider {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use gpui::{
|
|||||||
ease_in_out, svg, Animation, AnimationExt as _, ClickEvent, DismissEvent, Entity, EventEmitter,
|
ease_in_out, svg, Animation, AnimationExt as _, ClickEvent, DismissEvent, Entity, EventEmitter,
|
||||||
FocusHandle, Focusable, MouseDownEvent, Render,
|
FocusHandle, Focusable, MouseDownEvent, Render,
|
||||||
};
|
};
|
||||||
use language::language_settings::{AllLanguageSettings, InlineCompletionProvider};
|
use language::language_settings::{AllLanguageSettings, EditPredictionProvider};
|
||||||
use settings::{update_settings_file, Settings};
|
use settings::{update_settings_file, Settings};
|
||||||
use ui::{prelude::*, Checkbox, TintColor};
|
use ui::{prelude::*, Checkbox, TintColor};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
@@ -105,7 +105,7 @@ impl ZedPredictModal {
|
|||||||
update_settings_file::<AllLanguageSettings>(this.fs.clone(), cx, move |file, _| {
|
update_settings_file::<AllLanguageSettings>(this.fs.clone(), cx, move |file, _| {
|
||||||
file.features
|
file.features
|
||||||
.get_or_insert(Default::default())
|
.get_or_insert(Default::default())
|
||||||
.inline_completion_provider = Some(InlineCompletionProvider::Zed);
|
.edit_prediction_provider = Some(EditPredictionProvider::Zed);
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.emit(DismissEvent);
|
cx.emit(DismissEvent);
|
||||||
|
|||||||
@@ -1500,7 +1500,7 @@ impl ZetaInlineCompletionProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvider {
|
impl inline_completion::EditPredictionProvider for ZetaInlineCompletionProvider {
|
||||||
fn name() -> &'static str {
|
fn name() -> &'static str {
|
||||||
"zed-predict"
|
"zed-predict"
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -29,7 +29,7 @@ To use GitHub Copilot (enabled by default), add the following to your `settings.
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"features": {
|
"features": {
|
||||||
"inline_completion_provider": "copilot"
|
"edit_prediction_provider": "copilot"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -43,7 +43,7 @@ To use Supermaven, add the following to your `settings.json`:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"features": {
|
"features": {
|
||||||
"inline_completion_provider": "supermaven"
|
"edit_prediction_provider": "supermaven"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -56,23 +56,23 @@ Once you have configured an Edit Prediction provider, you can start using edit p
|
|||||||
|
|
||||||
There are a number of actions/shortcuts available to interact with edit predictions:
|
There are a number of actions/shortcuts available to interact with edit predictions:
|
||||||
|
|
||||||
- `editor: accept inline completion` (`tab`): To accept the current edit prediction
|
- `editor: accept edit prediction` (`tab`): To accept the current edit prediction
|
||||||
- `editor: accept partial inline completion` (`ctrl-cmd-right`): To accept the current edit prediction up to the next word boundary
|
- `editor: accept partial edit prediction` (`ctrl-cmd-right`): To accept the current edit prediction up to the next word boundary
|
||||||
- `editor: show inline completion` (`alt-tab`): Trigger an edit prediction request manually
|
- `editor: show edit prediction` (`alt-tab`): Trigger an edit prediction request manually
|
||||||
- `editor: next inline completion` (`alt-tab`): To cycle to the next edit prediction
|
- `editor: next edit prediction` (`alt-tab`): To cycle to the next edit prediction
|
||||||
- `editor: previous inline completion` (`alt-shift-tab`): To cycle to the previous edit prediction
|
- `editor: previous edit prediction` (`alt-shift-tab`): To cycle to the previous edit prediction
|
||||||
|
|
||||||
### Disabling Inline-Completions
|
### Disabling Edit Prediction
|
||||||
|
|
||||||
To disable completions that appear automatically as you type, add the following to your `settings.json`:
|
To disable predictions that appear automatically as you type, add the following to your `settings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"show_inline_completions": false
|
"show_edit_predictions": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can trigger edit predictions manually by executing `editor: show inline completion` (`alt-tab`).
|
You can trigger edit predictions manually by executing `editor: show edit prediction` (`alt-tab`).
|
||||||
|
|
||||||
You can also add this as a language-specific setting in your `settings.json` to disable edit predictions for a specific language:
|
You can also add this as a language-specific setting in your `settings.json` to disable edit predictions for a specific language:
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ You can also add this as a language-specific setting in your `settings.json` to
|
|||||||
{
|
{
|
||||||
"language": {
|
"language": {
|
||||||
"python": {
|
"python": {
|
||||||
"show_inline_completions": false
|
"show_edit_predictions": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -378,11 +378,11 @@ There are two options to choose from:
|
|||||||
## Edit Predictions
|
## Edit Predictions
|
||||||
|
|
||||||
- Description: Settings for edit predictions.
|
- Description: Settings for edit predictions.
|
||||||
- Setting: `inline_completions`
|
- Setting: `edit_predictions`
|
||||||
- Default:
|
- Default:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"inline_completions": {
|
"edit_predictions": {
|
||||||
"disabled_globs": [
|
"disabled_globs": [
|
||||||
"**/.env*",
|
"**/.env*",
|
||||||
"**/*.pem",
|
"**/*.pem",
|
||||||
@@ -409,7 +409,7 @@ List of `string` values
|
|||||||
## Edit Predictions Disabled in
|
## Edit Predictions Disabled in
|
||||||
|
|
||||||
- Description: A list of language scopes in which edit predictions should be disabled.
|
- Description: A list of language scopes in which edit predictions should be disabled.
|
||||||
- Setting: `inline_completions_disabled_in`
|
- Setting: `edit_predictions_disabled_in`
|
||||||
- Default: `[]`
|
- Default: `[]`
|
||||||
|
|
||||||
**Options**
|
**Options**
|
||||||
@@ -434,7 +434,7 @@ List of `string` values
|
|||||||
{
|
{
|
||||||
"languages": {
|
"languages": {
|
||||||
"Go": {
|
"Go": {
|
||||||
"inline_completions_disabled_in": ["comment", "string"]
|
"edit_predictions_disabled_in": ["comment", "string"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1478,7 +1478,7 @@ The following settings can be overridden for each specific language:
|
|||||||
- [`hard_tabs`](#hard-tabs)
|
- [`hard_tabs`](#hard-tabs)
|
||||||
- [`preferred_line_length`](#preferred-line-length)
|
- [`preferred_line_length`](#preferred-line-length)
|
||||||
- [`remove_trailing_whitespace_on_save`](#remove-trailing-whitespace-on-save)
|
- [`remove_trailing_whitespace_on_save`](#remove-trailing-whitespace-on-save)
|
||||||
- [`show_inline_completions`](#show-inline-completions)
|
- [`show_edit_predictions`](#show-edit-predictions)
|
||||||
- [`show_whitespaces`](#show-whitespaces)
|
- [`show_whitespaces`](#show-whitespaces)
|
||||||
- [`soft_wrap`](#soft-wrap)
|
- [`soft_wrap`](#soft-wrap)
|
||||||
- [`tab_size`](#tab-size)
|
- [`tab_size`](#tab-size)
|
||||||
@@ -1654,8 +1654,8 @@ Or to set a `socks5` proxy:
|
|||||||
|
|
||||||
## Show Edit Predictions
|
## Show Edit Predictions
|
||||||
|
|
||||||
- Description: Whether to show edit predictions as you type or manually by triggering `editor::ShowInlineCompletion`.
|
- Description: Whether to show edit predictions as you type or manually by triggering `editor::ShowEditPrediction`.
|
||||||
- Setting: `show_inline_completions`
|
- Setting: `show_edit_predictions`
|
||||||
- Default: `true`
|
- Default: `true`
|
||||||
|
|
||||||
**Options**
|
**Options**
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ command palette, by looking in the default keymaps for
|
|||||||
or
|
or
|
||||||
[Linux](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-linux.json), or by using Zed's autocomplete in your keymap file.
|
[Linux](https://github.com/zed-industries/zed/blob/main/assets/keymaps/default-linux.json), or by using Zed's autocomplete in your keymap file.
|
||||||
|
|
||||||
Most actions do not require any arguments, and so you can bind them as strings: `"ctrl-a": "language_selector::Toggle"`. Some require a single argument, and must be bound as an array: `"ctrl-a": ["workspace::ActivatePaneInDirection", "down"]`. Some actions require multiple arguments, and are bound as an array of a string and an object: `"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]`.
|
Most actions do not require any arguments, and so you can bind them as strings: `"ctrl-a": "language_selector::Toggle"`. Some require a single argument, and must be bound as an array: `"cmd-1": ["workspace::ActivatePane", 0]`. Some actions require multiple arguments, and are bound as an array of a string and an object: `"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]`.
|
||||||
|
|
||||||
### Precedence
|
### Precedence
|
||||||
|
|
||||||
|
|||||||
+7
-12
@@ -368,10 +368,10 @@ But you cannot use the same shortcuts to move between all the editor docks (the
|
|||||||
{
|
{
|
||||||
"context": "Dock",
|
"context": "Dock",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
|
"ctrl-w h": "workspace::ActivatePaneLeft",
|
||||||
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
|
"ctrl-w l": "workspace::ActivatePaneRight",
|
||||||
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
|
"ctrl-w k": "workspace::ActivatePaneUp",
|
||||||
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"]
|
"ctrl-w j": "workspace::ActivatePaneDown"
|
||||||
// ... or other keybindings
|
// ... or other keybindings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,12 +399,7 @@ Vim mode comes with shortcuts to surround the selection in normal mode (`ys`), b
|
|||||||
{
|
{
|
||||||
"context": "vim_mode == visual",
|
"context": "vim_mode == visual",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"shift-s": [
|
"shift-s": ["vim::PushAddSurrounds", {}]
|
||||||
"vim::PushOperator",
|
|
||||||
{
|
|
||||||
"AddSurrounds": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -416,8 +411,8 @@ The [Sneak motion](https://github.com/justinmk/vim-sneak) feature allows for qui
|
|||||||
{
|
{
|
||||||
"context": "vim_mode == normal || vim_mode == visual",
|
"context": "vim_mode == normal || vim_mode == visual",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"s": ["vim::PushOperator", { "Sneak": {} }],
|
"s": ["vim::PushSneak", {}],
|
||||||
"S": ["vim::PushOperator", { "SneakBackward": {} }]
|
"S": ["vim::PushSneakBackward", {}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in new issue
Block a user