mirror of
https://github.com/zed-industries/zed.git
synced 2026-05-24 13:39:08 +00:00
settings: Add auto completion to command aliases setting (#54496)
Update the JSON schema generated for the settings file in order to be able to provide the list of valid actions when editing the values for the `command_aliases` setting. While reviewing https://github.com/zed-industries/zed/pull/52892 , I noticed that, even though we already have support for this in the keymap file, we don't support it for the `command_aliases` setting, so went ahead and refactored this a bit such that the existing functionality for the keymap file JSON schema could also be re-used for the `command_aliases` setting. Here's a quick big-picture breakdown of the relevant changes: * Add `settings_content::ActionName` newtype, representing a simple named action without arguments. The `settings_content::ActionName::build_schema` function can be used to build the schema of all possible action names. * Add `settings_content::ActionWithArguments` newtype, representing an action with arguments. This was mostly done so as to keep both action without arguments and action with arguments newtypes together, even though we don't have `settings_content::ActionWithArguments::build_schema`, as it is only used by the keymap schema generation logic and probably doesn't warrant moving it here right now. * Update both `settings_content::WorkspaceSettingsContent::command_aliases` and `workspace::workspace_settings::WorkspaceSettings::command_aliases` to now be of type `HashMap<String, ActionName>` such that, when the json schema for `command_aliases` is generate, it'll now reference the `#/$defs/ActionName` schema. * Update `SettingsStore::json_schema` so as to populate the `#/$defs/ActionName` schema at runtime, replacing it with the actual list of valid action names. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Added support for auto-completing action names on `command_aliases` setting
This commit is contained in:
parent
2eafa6e6aa
commit
b7d35e528a
10 changed files with 294 additions and 28 deletions
|
|
@ -442,7 +442,7 @@ impl PickerDelegate for CommandPaletteDelegate {
|
|||
) -> gpui::Task<()> {
|
||||
let settings = WorkspaceSettings::get_global(cx);
|
||||
if let Some(alias) = settings.command_aliases.get(&query) {
|
||||
query = alias.to_string();
|
||||
query = alias.as_ref().to_owned();
|
||||
}
|
||||
|
||||
let workspace = self.workspace.clone();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use mdbook::BookItem;
|
|||
use mdbook::book::{Book, Chapter};
|
||||
use mdbook::preprocess::CmdPreprocessor;
|
||||
use regex::Regex;
|
||||
use settings::{KeymapFile, SettingsStore};
|
||||
use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::io::{self, Read};
|
||||
|
|
@ -369,7 +369,18 @@ fn find_binding_with_overlay(
|
|||
}
|
||||
|
||||
fn template_and_validate_json_snippets(book: &mut Book, errors: &mut HashSet<PreprocessorError>) {
|
||||
let settings_schema = SettingsStore::json_schema(&Default::default());
|
||||
let params = SettingsJsonSchemaParams {
|
||||
language_names: &[],
|
||||
font_names: &[],
|
||||
theme_names: &[],
|
||||
icon_theme_names: &[],
|
||||
lsp_adapter_names: &[],
|
||||
action_names: &[],
|
||||
action_documentation: &HashMap::default(),
|
||||
deprecations: &HashMap::default(),
|
||||
deprecation_messages: &HashMap::default(),
|
||||
};
|
||||
let settings_schema = SettingsStore::json_schema(¶ms);
|
||||
let settings_validator = jsonschema::validator_for(&settings_schema)
|
||||
.expect("failed to compile settings JSON schema");
|
||||
|
||||
|
|
|
|||
|
|
@ -352,6 +352,11 @@ async fn resolve_dynamic_schema(
|
|||
let icon_theme_names = icon_theme_names.as_slice();
|
||||
let theme_names = theme_names.as_slice();
|
||||
|
||||
let action_names = cx.all_action_names();
|
||||
let action_documentation = cx.action_documentation();
|
||||
let deprecations = cx.deprecated_actions_to_preferred_actions();
|
||||
let deprecation_messages = cx.action_deprecation_messages();
|
||||
|
||||
let mut schema =
|
||||
settings::SettingsStore::json_schema(&settings::SettingsJsonSchemaParams {
|
||||
language_names,
|
||||
|
|
@ -359,6 +364,10 @@ async fn resolve_dynamic_schema(
|
|||
theme_names,
|
||||
icon_theme_names,
|
||||
lsp_adapter_names: &lsp_adapter_names,
|
||||
action_names,
|
||||
action_documentation,
|
||||
deprecations,
|
||||
deprecation_messages,
|
||||
});
|
||||
inject_feature_flags_schema(&mut schema);
|
||||
schema
|
||||
|
|
@ -387,6 +396,10 @@ async fn resolve_dynamic_schema(
|
|||
font_names: &[],
|
||||
theme_names: &[],
|
||||
icon_theme_names: &[],
|
||||
action_names: &[],
|
||||
action_documentation: &HashMap::default(),
|
||||
deprecations: &HashMap::default(),
|
||||
deprecation_messages: &HashMap::default(),
|
||||
});
|
||||
inject_feature_flags_schema(&mut schema);
|
||||
schema
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use util::{
|
|||
};
|
||||
|
||||
use crate::SettingsAssets;
|
||||
use settings_content::{ActionName, ActionWithArguments};
|
||||
use settings_json::{
|
||||
append_top_level_array_value_in_json_text, parse_json_with_comments,
|
||||
replace_top_level_array_value_in_json_text,
|
||||
|
|
@ -698,10 +699,17 @@ impl KeymapFile {
|
|||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
});
|
||||
let mut keymap_action_alternatives = vec![
|
||||
empty_action_name.clone(),
|
||||
empty_action_name_with_input.clone(),
|
||||
];
|
||||
|
||||
let mut keymap_deprecations = deprecations.clone();
|
||||
keymap_deprecations.insert(NoAction.name(), "null");
|
||||
let action_name_schema = ActionName::build_schema(
|
||||
action_schemas.iter().map(|(name, _)| *name),
|
||||
action_documentation,
|
||||
&keymap_deprecations,
|
||||
deprecation_messages,
|
||||
);
|
||||
|
||||
let mut action_with_arguments_alternatives = vec![empty_action_name_with_input.clone()];
|
||||
let mut unbind_target_action_alternatives =
|
||||
vec![empty_action_name, empty_action_name_with_input];
|
||||
|
||||
|
|
@ -731,7 +739,6 @@ impl KeymapFile {
|
|||
if let Some(description) = &description {
|
||||
add_description(&mut plain_action, description);
|
||||
}
|
||||
keymap_action_alternatives.push(plain_action.clone());
|
||||
if include_in_unbind_target_schema {
|
||||
unbind_target_action_alternatives.push(plain_action);
|
||||
}
|
||||
|
|
@ -760,7 +767,7 @@ impl KeymapFile {
|
|||
"minItems": 2,
|
||||
"maxItems": 2
|
||||
});
|
||||
keymap_action_alternatives.push(action_with_input.clone());
|
||||
action_with_arguments_alternatives.push(action_with_input.clone());
|
||||
if include_in_unbind_target_schema {
|
||||
unbind_target_action_alternatives.push(action_with_input);
|
||||
}
|
||||
|
|
@ -789,7 +796,7 @@ impl KeymapFile {
|
|||
"This action does not take input - just the action name string should be used."
|
||||
.to_string(),
|
||||
);
|
||||
keymap_action_alternatives.push(actions_with_empty_input);
|
||||
action_with_arguments_alternatives.push(actions_with_empty_input);
|
||||
}
|
||||
|
||||
if !empty_schema_unbind_target_action_names.is_empty() {
|
||||
|
|
@ -812,17 +819,22 @@ impl KeymapFile {
|
|||
unbind_target_action_alternatives.push(actions_with_empty_input);
|
||||
}
|
||||
|
||||
// Placing null first causes json-language-server to default assuming actions should be
|
||||
// null, so place it last.
|
||||
keymap_action_alternatives.push(json_schema!({
|
||||
"type": "null"
|
||||
}));
|
||||
generator.definitions_mut().insert(
|
||||
ActionName::schema_name().to_string(),
|
||||
action_name_schema.to_value(),
|
||||
);
|
||||
generator.definitions_mut().insert(
|
||||
ActionWithArguments::schema_name().to_string(),
|
||||
json!({ "anyOf": action_with_arguments_alternatives }),
|
||||
);
|
||||
|
||||
generator.definitions_mut().insert(
|
||||
KeymapAction::schema_name().to_string(),
|
||||
json!({
|
||||
"anyOf": keymap_action_alternatives
|
||||
}),
|
||||
json!({ "anyOf": [
|
||||
{ "$ref": format!("#/$defs/{}", ActionName::schema_name().to_string()) },
|
||||
{ "$ref": format!("#/$defs/{}", ActionWithArguments::schema_name().to_string()) },
|
||||
{ "type": "null" }
|
||||
] }),
|
||||
);
|
||||
generator.definitions_mut().insert(
|
||||
UnbindTargetAction::schema_name().to_string(),
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use gpui::{
|
|||
use paths::{local_settings_file_relative_path, task_file_name};
|
||||
use schemars::{JsonSchema, json_schema};
|
||||
use serde_json::Value;
|
||||
use settings_content::ParseStatus;
|
||||
use settings_content::{ActionName, ParseStatus};
|
||||
use std::{
|
||||
any::{Any, TypeId, type_name},
|
||||
fmt::Debug,
|
||||
|
|
@ -272,13 +272,16 @@ pub trait AnySettingValue: 'static + Send + Sync {
|
|||
}
|
||||
|
||||
/// Parameters that are used when generating some JSON schemas at runtime.
|
||||
#[derive(Default)]
|
||||
pub struct SettingsJsonSchemaParams<'a> {
|
||||
pub language_names: &'a [String],
|
||||
pub font_names: &'a [String],
|
||||
pub theme_names: &'a [SharedString],
|
||||
pub icon_theme_names: &'a [SharedString],
|
||||
pub lsp_adapter_names: &'a [String],
|
||||
pub action_names: &'a [&'a str],
|
||||
pub action_documentation: &'a HashMap<&'a str, &'a str>,
|
||||
pub deprecations: &'a HashMap<&'a str, &'a str>,
|
||||
pub deprecation_messages: &'a HashMap<&'a str, &'a str>,
|
||||
}
|
||||
|
||||
impl SettingsStore {
|
||||
|
|
@ -1263,6 +1266,17 @@ impl SettingsStore {
|
|||
});
|
||||
}
|
||||
|
||||
if !params.action_names.is_empty() {
|
||||
replace_subschema::<ActionName>(&mut generator, || {
|
||||
ActionName::build_schema(
|
||||
params.action_names.iter().copied(),
|
||||
params.action_documentation,
|
||||
params.deprecations,
|
||||
params.deprecation_messages,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
generator
|
||||
.root_schema_for::<UserSettingsContent>()
|
||||
.to_value()
|
||||
|
|
@ -2738,6 +2752,10 @@ mod tests {
|
|||
"rust-analyzer".to_string(),
|
||||
"typescript-language-server".to_string(),
|
||||
],
|
||||
action_names: &[],
|
||||
action_documentation: &HashMap::default(),
|
||||
deprecations: &HashMap::default(),
|
||||
deprecation_messages: &HashMap::default(),
|
||||
});
|
||||
|
||||
let properties = schema
|
||||
|
|
@ -2789,6 +2807,10 @@ mod tests {
|
|||
"rust-analyzer".to_string(),
|
||||
"typescript-language-server".to_string(),
|
||||
],
|
||||
action_names: &[],
|
||||
action_documentation: &HashMap::default(),
|
||||
deprecations: &HashMap::default(),
|
||||
deprecation_messages: &HashMap::default(),
|
||||
});
|
||||
|
||||
let properties = schema
|
||||
|
|
@ -2837,6 +2859,10 @@ mod tests {
|
|||
theme_names: &["One Dark".into()],
|
||||
icon_theme_names: &["Zed Icons".into()],
|
||||
lsp_adapter_names: &["rust-analyzer".to_string()],
|
||||
action_names: &[],
|
||||
action_documentation: &HashMap::default(),
|
||||
deprecations: &HashMap::default(),
|
||||
deprecation_messages: &HashMap::default(),
|
||||
};
|
||||
|
||||
let user_schema = SettingsStore::json_schema(¶ms);
|
||||
|
|
|
|||
202
crates/settings_content/src/action.rs
Normal file
202
crates/settings_content/src/action.rs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
use collections::HashMap;
|
||||
use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use settings_macros::MergeFrom;
|
||||
|
||||
/// The name of a registered GPUI action, serialized as a plain JSON string, for
|
||||
/// example, "editor::Cancel"` or `"workspace::CloseActiveItem"`.
|
||||
///
|
||||
/// This newtype exists so that settings fields like `command_aliases`, or the
|
||||
/// keymap file bindings, can request JSON-schema auto completion over the set
|
||||
/// of actions known at runtime.
|
||||
#[derive(Serialize, Deserialize, Default, MergeFrom, Clone, Debug, PartialEq)]
|
||||
#[serde(transparent)]
|
||||
pub struct ActionName(String);
|
||||
|
||||
/// Small helper function to populate the schema's `deprecationMessage` field with the
|
||||
/// provided deprecation message.
|
||||
fn add_deprecation(schema: &mut Schema, message: String) {
|
||||
schema.insert("deprecationMessage".into(), Value::String(message));
|
||||
}
|
||||
|
||||
/// Small helper function to populate the schema's `description` field with the
|
||||
/// provided description.
|
||||
fn add_description(schema: &mut Schema, description: &str) {
|
||||
schema.insert("description".into(), Value::String(description.to_string()));
|
||||
}
|
||||
|
||||
impl ActionName {
|
||||
pub fn new(name: impl Into<String>) -> Self {
|
||||
Self(name.into())
|
||||
}
|
||||
|
||||
/// Build the JSON schema to be used for `$defs/ActionName`, basically an
|
||||
/// `anyOf` of all of the available actions with per-action documentation
|
||||
/// and deprecation metadata attached.
|
||||
pub fn build_schema<'a>(
|
||||
action_names: impl IntoIterator<Item = &'a str>,
|
||||
action_documentation: &HashMap<&str, &str>,
|
||||
deprecations: &HashMap<&str, &str>,
|
||||
deprecation_messages: &HashMap<&str, &str>,
|
||||
) -> Schema {
|
||||
let mut alternatives = Vec::new();
|
||||
|
||||
for action_name in action_names {
|
||||
let mut entry = json_schema!({
|
||||
"type": "string",
|
||||
"const": action_name
|
||||
});
|
||||
|
||||
if let Some(message) = deprecation_messages.get(action_name) {
|
||||
add_deprecation(&mut entry, message.to_string());
|
||||
} else if let Some(new_name) = deprecations.get(action_name) {
|
||||
add_deprecation(&mut entry, format!("Deprecated, use {new_name}"));
|
||||
}
|
||||
|
||||
if let Some(description) = action_documentation.get(action_name) {
|
||||
add_description(&mut entry, description);
|
||||
}
|
||||
|
||||
alternatives.push(entry);
|
||||
}
|
||||
|
||||
json_schema!({ "anyOf": alternatives })
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ActionName {
|
||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
|
||||
write!(formatter, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ActionName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for ActionName {
|
||||
/// The name under which this type should be stored in a generator's `$defs`
|
||||
/// map when schemars encounters it during schema generation.
|
||||
/// Keeping it stable as `"ActionName"` lets consumers reference it by
|
||||
/// `#/$defs/ActionName` and lets [`util::schemars::replace_subschema`] look
|
||||
/// it up at runtime to swap in the real schema.
|
||||
fn schema_name() -> Cow<'static, str> {
|
||||
"ActionName".into()
|
||||
}
|
||||
|
||||
/// Returns `true` as a placeholder.
|
||||
///
|
||||
/// The real schema, an `anyOf` of every registered action name with action
|
||||
/// documentation and deprecation metadata, cannot be produced here because
|
||||
/// `JsonSchema::json_schema` receives no runtime context. It is instead
|
||||
/// built by call sites that do have access to the GPUI action registry
|
||||
/// using [`ActionName::build_schema`].
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Schema {
|
||||
json_schema!(true)
|
||||
}
|
||||
}
|
||||
|
||||
/// A GPUI action together with its input data, serialized as a two-element JSON
|
||||
/// array of the form `["namespace::Name", { ... }]`, for example,
|
||||
/// `["pane::ActivateItem", { "index": 0 }]`.
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(transparent)]
|
||||
pub struct ActionWithArguments(pub Value);
|
||||
|
||||
impl JsonSchema for ActionWithArguments {
|
||||
/// The name under which this type should be stored in a generator's `$defs`
|
||||
/// map when schemars encounters it during schema generation.
|
||||
/// Keeping it stable as `"ActionWithArguments"` lets consumers reference it
|
||||
/// by `#/$defs/ActionWithArguments` and lets
|
||||
/// [`util::schemars::replace_subschema`] look it up at runtime to swap in
|
||||
/// the real schema.
|
||||
fn schema_name() -> Cow<'static, str> {
|
||||
"ActionWithArguments".into()
|
||||
}
|
||||
|
||||
/// Returns `true` as a placeholder.
|
||||
///
|
||||
/// The real schema, an `anyOf` of every registered action name that
|
||||
/// supports arguments, with action documentation and deprecation metadata,
|
||||
/// cannot be produced here because `JsonSchema::json_schema` receives no
|
||||
/// runtime context. At the time of writing, it is instead built by
|
||||
/// [`KeymapFile::generate_json_schema`], where all of the runtime
|
||||
/// information is available.
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Schema {
|
||||
json_schema!(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn build_schema_produces_anyof_of_consts_per_name() {
|
||||
let mut action_documentation = HashMap::default();
|
||||
let mut deprecations = HashMap::default();
|
||||
let mut deprecation_messages = HashMap::default();
|
||||
action_documentation.insert("editor::Cancel", "Cancel the current operation.");
|
||||
deprecations.insert("workspace::CloseCurrentItem", "workspace::CloseActiveItem");
|
||||
deprecation_messages.insert("editor::Explode", "DO NOT USE!");
|
||||
|
||||
let schema = ActionName::build_schema(
|
||||
[
|
||||
"editor::Cancel",
|
||||
"editor::Explode",
|
||||
"workspace::CloseCurrentItem",
|
||||
"workspace::CloseActiveItem",
|
||||
],
|
||||
&action_documentation,
|
||||
&deprecations,
|
||||
&deprecation_messages,
|
||||
);
|
||||
|
||||
let value = schema.to_value();
|
||||
let values = value
|
||||
.pointer("/anyOf")
|
||||
.and_then(|v| v.as_array())
|
||||
.expect("anyOf should be present");
|
||||
assert_eq!(values.len(), 4);
|
||||
|
||||
let (name, schema_type, description) = (
|
||||
values[0].get("const").and_then(Value::as_str),
|
||||
values[0].get("type").and_then(Value::as_str),
|
||||
values[0].get("description").and_then(Value::as_str),
|
||||
);
|
||||
assert_eq!(name, Some("editor::Cancel"));
|
||||
assert_eq!(schema_type, Some("string"));
|
||||
assert_eq!(description, Some("Cancel the current operation."));
|
||||
|
||||
let (name, schema_type, message) = (
|
||||
values[1].get("const").and_then(Value::as_str),
|
||||
values[1].get("type").and_then(Value::as_str),
|
||||
values[1].get("deprecationMessage").and_then(Value::as_str),
|
||||
);
|
||||
assert_eq!(name, Some("editor::Explode"));
|
||||
assert_eq!(schema_type, Some("string"));
|
||||
assert_eq!(message, Some("DO NOT USE!"));
|
||||
|
||||
let (name, schema_type, message) = (
|
||||
values[2].get("const").and_then(Value::as_str),
|
||||
values[2].get("type").and_then(Value::as_str),
|
||||
values[2].get("deprecationMessage").and_then(Value::as_str),
|
||||
);
|
||||
assert_eq!(name, Some("workspace::CloseCurrentItem"));
|
||||
assert_eq!(schema_type, Some("string"));
|
||||
assert_eq!(message, Some("Deprecated, use workspace::CloseActiveItem"));
|
||||
|
||||
let (name, schema_type) = (
|
||||
values[3].get("const").and_then(Value::as_str),
|
||||
values[3].get("type").and_then(Value::as_str),
|
||||
);
|
||||
assert_eq!(name, Some("workspace::CloseActiveItem"));
|
||||
assert_eq!(schema_type, Some("string"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod action;
|
||||
mod agent;
|
||||
mod editor;
|
||||
mod extension;
|
||||
|
|
@ -12,6 +13,7 @@ mod theme;
|
|||
mod title_bar;
|
||||
mod workspace;
|
||||
|
||||
pub use action::{ActionName, ActionWithArguments};
|
||||
pub use agent::*;
|
||||
pub use editor::*;
|
||||
pub use extension::*;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize};
|
|||
use settings_macros::{MergeFrom, with_fallible_options};
|
||||
|
||||
use crate::{
|
||||
CenteredPaddingSettings, DelayMs, DockPosition, DockSide, InactiveOpacity, ShowIndentGuides,
|
||||
ShowScrollbar, serialize_optional_f32_with_two_decimal_places,
|
||||
ActionName, CenteredPaddingSettings, DelayMs, DockPosition, DockSide, InactiveOpacity,
|
||||
ShowIndentGuides, ShowScrollbar, serialize_optional_f32_with_two_decimal_places,
|
||||
};
|
||||
|
||||
#[with_fallible_options]
|
||||
|
|
@ -88,9 +88,9 @@ pub struct WorkspaceSettingsContent {
|
|||
/// Aliases for the command palette. When you type a key in this map,
|
||||
/// it will be assumed to equal the value.
|
||||
///
|
||||
/// Default: true
|
||||
/// Default: {}
|
||||
#[serde(default)]
|
||||
pub command_aliases: HashMap<String, String>,
|
||||
pub command_aliases: HashMap<String, ActionName>,
|
||||
/// Maximum open tabs in a pane. Will not close an unsaved
|
||||
/// tab. Set to `None` for unlimited tabs.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use gpui::{KeyBinding, Modifiers, MouseButton, TestAppContext, px};
|
|||
use itertools::Itertools;
|
||||
use language::{CursorShape, Language, LanguageConfig, Point};
|
||||
pub use neovim_backed_test_context::*;
|
||||
use settings::SettingsStore;
|
||||
use settings::{ActionName, SettingsStore};
|
||||
use ui::Pixels;
|
||||
use util::{path, test::marked_text_ranges};
|
||||
pub use vim_test_context::*;
|
||||
|
|
@ -1926,7 +1926,7 @@ async fn test_command_alias(cx: &mut gpui::TestAppContext) {
|
|||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings(cx, |s| {
|
||||
let mut aliases = HashMap::default();
|
||||
aliases.insert("Q".to_string(), "upper".to_string());
|
||||
aliases.insert("Q".to_string(), ActionName::new("upper"));
|
||||
s.workspace.command_aliases = aliases
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::DockPosition;
|
|||
use collections::HashMap;
|
||||
use serde::Deserialize;
|
||||
pub use settings::{
|
||||
AutosaveSetting, BottomDockLayout, EncodingDisplayOptions, InactiveOpacity,
|
||||
ActionName, AutosaveSetting, BottomDockLayout, EncodingDisplayOptions, InactiveOpacity,
|
||||
PaneSplitDirectionHorizontal, PaneSplitDirectionVertical, RegisterSetting,
|
||||
RestoreOnStartupBehavior, Settings,
|
||||
};
|
||||
|
|
@ -25,7 +25,7 @@ pub struct WorkspaceSettings {
|
|||
pub drop_target_size: f32,
|
||||
pub use_system_path_prompts: bool,
|
||||
pub use_system_prompts: bool,
|
||||
pub command_aliases: HashMap<String, String>,
|
||||
pub command_aliases: HashMap<String, ActionName>,
|
||||
pub max_tabs: Option<NonZeroUsize>,
|
||||
pub when_closing_with_no_tabs: settings::CloseWindowWhenNoItems,
|
||||
pub on_last_window_closed: settings::OnLastWindowClosed,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue