Add settings to remote servers, use XDG paths on remote, and enable node LSPs (#19176)

Supersedes https://github.com/zed-industries/zed/pull/19166

TODO:
- [x] Update basic zed paths
- [x] update create_state_directory
- [x] Use this with `NodeRuntime`
- [x] Add server settings
- [x] Add an 'open server settings command'
- [x] Make sure it all works


Release Notes:

- Updated the actions `zed::OpenLocalSettings` and `zed::OpenLocalTasks`
to `zed::OpenProjectSettings` and `zed::OpenProjectTasks`.

---------

Co-authored-by: Conrad <conrad@zed.dev>
Co-authored-by: Richard <richard@zed.dev>
This commit is contained in:
Mikayla Maki 2024-10-15 23:32:44 -07:00 committed by GitHub
parent 1dda039f38
commit f944ebc4cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 804 additions and 218 deletions

View file

@ -88,7 +88,11 @@ pub fn initial_user_settings_content() -> Cow<'static, str> {
asset_str::<SettingsAssets>("settings/initial_user_settings.json")
}
pub fn initial_local_settings_content() -> Cow<'static, str> {
pub fn initial_server_settings_content() -> Cow<'static, str> {
asset_str::<SettingsAssets>("settings/initial_server_settings.json")
}
pub fn initial_project_settings_content() -> Cow<'static, str> {
asset_str::<SettingsAssets>("settings/initial_local_settings.json")
}

View file

@ -110,6 +110,8 @@ pub struct SettingsSources<'a, T> {
pub user: Option<&'a T>,
/// The user settings for the current release channel.
pub release_channel: Option<&'a T>,
/// The server's settings.
pub server: Option<&'a T>,
/// The project settings, ordered from least specific to most specific.
pub project: &'a [&'a T],
}
@ -126,6 +128,7 @@ impl<'a, T: Serialize> SettingsSources<'a, T> {
.into_iter()
.chain(self.user)
.chain(self.release_channel)
.chain(self.server)
.chain(self.project.iter().copied())
}
@ -162,6 +165,7 @@ pub struct SettingsStore {
setting_values: HashMap<TypeId, Box<dyn AnySettingValue>>,
raw_default_settings: serde_json::Value,
raw_user_settings: serde_json::Value,
raw_server_settings: Option<serde_json::Value>,
raw_extension_settings: serde_json::Value,
raw_local_settings:
BTreeMap<(WorktreeId, Arc<Path>), HashMap<LocalSettingsKind, serde_json::Value>>,
@ -219,6 +223,7 @@ impl SettingsStore {
setting_values: Default::default(),
raw_default_settings: serde_json::json!({}),
raw_user_settings: serde_json::json!({}),
raw_server_settings: None,
raw_extension_settings: serde_json::json!({}),
raw_local_settings: Default::default(),
tab_size_callback: Default::default(),
@ -269,6 +274,13 @@ impl SettingsStore {
.log_err();
}
let server_value = self
.raw_server_settings
.as_ref()
.and_then(|server_setting| {
setting_value.deserialize_setting(server_setting).log_err()
});
let extension_value = setting_value
.deserialize_setting(&self.raw_extension_settings)
.log_err();
@ -277,9 +289,10 @@ impl SettingsStore {
.load_setting(
SettingsSources {
default: &default_settings,
release_channel: release_channel_value.as_ref(),
extensions: extension_value.as_ref(),
user: user_value.as_ref(),
release_channel: release_channel_value.as_ref(),
server: server_value.as_ref(),
project: &[],
},
cx,
@ -522,6 +535,29 @@ impl SettingsStore {
Ok(())
}
pub fn set_server_settings(
&mut self,
server_settings_content: &str,
cx: &mut AppContext,
) -> Result<()> {
let settings: Option<serde_json::Value> = if server_settings_content.is_empty() {
None
} else {
parse_json_with_comments(server_settings_content)?
};
anyhow::ensure!(
settings
.as_ref()
.map(|value| value.is_object())
.unwrap_or(true),
"settings must be an object"
);
self.raw_server_settings = settings;
self.recompute_values(None, cx)?;
Ok(())
}
/// Add or remove a set of local settings via a JSON string.
pub fn set_local_settings(
&mut self,
@ -530,8 +566,8 @@ impl SettingsStore {
kind: LocalSettingsKind,
settings_content: Option<&str>,
cx: &mut AppContext,
) -> Result<()> {
anyhow::ensure!(
) -> std::result::Result<(), InvalidSettingsError> {
debug_assert!(
kind != LocalSettingsKind::Tasks,
"Attempted to submit tasks into the settings store"
);
@ -541,7 +577,13 @@ impl SettingsStore {
.entry((root_id, directory_path.clone()))
.or_default();
let changed = if settings_content.is_some_and(|content| !content.is_empty()) {
let new_contents = parse_json_with_comments(settings_content.unwrap())?;
let new_contents =
parse_json_with_comments(settings_content.unwrap()).map_err(|e| {
InvalidSettingsError::LocalSettings {
path: directory_path.join(local_settings_file_relative_path()),
message: e.to_string(),
}
})?;
if Some(&new_contents) == raw_local_settings.get(&kind) {
false
} else {
@ -711,12 +753,16 @@ impl SettingsStore {
&mut self,
changed_local_path: Option<(WorktreeId, &Path)>,
cx: &mut AppContext,
) -> Result<()> {
) -> Result<(), InvalidSettingsError> {
// Reload the global and local values for every setting.
let mut project_settings_stack = Vec::<DeserializedSetting>::new();
let mut paths_stack = Vec::<Option<(WorktreeId, &Path)>>::new();
for setting_value in self.setting_values.values_mut() {
let default_settings = setting_value.deserialize_setting(&self.raw_default_settings)?;
let default_settings = setting_value
.deserialize_setting(&self.raw_default_settings)
.map_err(|e| InvalidSettingsError::DefaultSettings {
message: e.to_string(),
})?;
let extension_settings = setting_value
.deserialize_setting(&self.raw_extension_settings)
@ -725,12 +771,17 @@ impl SettingsStore {
let user_settings = match setting_value.deserialize_setting(&self.raw_user_settings) {
Ok(settings) => Some(settings),
Err(error) => {
return Err(anyhow!(InvalidSettingsError::UserSettings {
message: error.to_string()
}));
return Err(InvalidSettingsError::UserSettings {
message: error.to_string(),
});
}
};
let server_settings = self
.raw_server_settings
.as_ref()
.and_then(|setting| setting_value.deserialize_setting(setting).log_err());
let mut release_channel_settings = None;
if let Some(release_settings) = &self
.raw_user_settings
@ -753,6 +804,7 @@ impl SettingsStore {
extensions: extension_settings.as_ref(),
user: user_settings.as_ref(),
release_channel: release_channel_settings.as_ref(),
server: server_settings.as_ref(),
project: &[],
},
cx,
@ -804,6 +856,7 @@ impl SettingsStore {
extensions: extension_settings.as_ref(),
user: user_settings.as_ref(),
release_channel: release_channel_settings.as_ref(),
server: server_settings.as_ref(),
project: &project_settings_stack.iter().collect::<Vec<_>>(),
},
cx,
@ -818,10 +871,10 @@ impl SettingsStore {
}
}
Err(error) => {
return Err(anyhow!(InvalidSettingsError::LocalSettings {
return Err(InvalidSettingsError::LocalSettings {
path: directory_path.join(local_settings_file_relative_path()),
message: error.to_string()
}));
message: error.to_string(),
});
}
}
}
@ -835,13 +888,17 @@ impl SettingsStore {
pub enum InvalidSettingsError {
LocalSettings { path: PathBuf, message: String },
UserSettings { message: String },
ServerSettings { message: String },
DefaultSettings { message: String },
}
impl std::fmt::Display for InvalidSettingsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
InvalidSettingsError::LocalSettings { message, .. }
| InvalidSettingsError::UserSettings { message } => {
| InvalidSettingsError::UserSettings { message }
| InvalidSettingsError::ServerSettings { message }
| InvalidSettingsError::DefaultSettings { message } => {
write!(f, "{}", message)
}
}
@ -893,6 +950,9 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
release_channel: values
.release_channel
.map(|value| value.0.downcast_ref::<T::FileContent>().unwrap()),
server: values
.server
.map(|value| value.0.downcast_ref::<T::FileContent>().unwrap()),
project: values
.project
.iter()