settings: Make external formatter arguments optional (#18340)

If specifying a formatter in the settings like this:

    "languages": {
      "foo": {
        "formatter": {
          "external": {
            "command": "/path/to/foo-formatter"
          }
        }
      }
    }

Zed will show an error like this:

    Invalid user settings file
    data did not match any variant of untagged enum SingleOrVec

This is because the arguments are not optional. The error is hard to
understand, so let's make the arguments actually optional, which makes
the above settings snippet valid.

Release Notes:

- Make external formatter arguments optional
This commit is contained in:
Tom Wieczorek 2024-09-30 08:34:41 +02:00 committed by GitHub
parent 250f2e76eb
commit 77df7e56f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 22 additions and 13 deletions

View file

@ -4409,7 +4409,7 @@ async fn test_formatting_buffer(
file.defaults.formatter = Some(SelectedFormatter::List(FormatterList(
vec![Formatter::External {
command: "awk".into(),
arguments: vec!["{sub(/two/,\"{buffer_path}\")}1".to_string()].into(),
arguments: Some(vec!["{sub(/two/,\"{buffer_path}\")}1".to_string()].into()),
}]
.into(),
)));

View file

@ -661,7 +661,7 @@ pub enum Formatter {
/// The external program to run.
command: Arc<str>,
/// The arguments to pass to the program.
arguments: Arc<[String]>,
arguments: Option<Arc<[String]>>,
},
/// Files should be formatted using code actions executed by language servers.
CodeActions(HashMap<String, bool>),

View file

@ -539,13 +539,19 @@ impl LocalLspStore {
}
Formatter::External { command, arguments } => {
let buffer_abs_path = buffer_abs_path.as_ref().map(|path| path.as_path());
Self::format_via_external_command(buffer, buffer_abs_path, command, arguments, cx)
.await
.context(format!(
"failed to format via external command {:?}",
command
))?
.map(FormatOperation::External)
Self::format_via_external_command(
buffer,
buffer_abs_path,
command,
arguments.as_deref(),
cx,
)
.await
.context(format!(
"failed to format via external command {:?}",
command
))?
.map(FormatOperation::External)
}
Formatter::CodeActions(code_actions) => {
let code_actions = deserialize_code_actions(code_actions);
@ -571,7 +577,7 @@ impl LocalLspStore {
buffer: &Model<Buffer>,
buffer_abs_path: Option<&Path>,
command: &str,
arguments: &[String],
arguments: Option<&[String]>,
cx: &mut AsyncAppContext,
) -> Result<Option<Diff>> {
let working_dir_path = buffer.update(cx, |buffer, cx| {
@ -595,14 +601,17 @@ impl LocalLspStore {
child.current_dir(working_dir_path);
}
let mut child = child
.args(arguments.iter().map(|arg| {
if let Some(arguments) = arguments {
child.args(arguments.iter().map(|arg| {
if let Some(buffer_abs_path) = buffer_abs_path {
arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy())
} else {
arg.replace("{buffer_path}", "Untitled")
}
}))
}));
}
let mut child = child
.stdin(smol::process::Stdio::piped())
.stdout(smol::process::Stdio::piped())
.stderr(smol::process::Stdio::piped())