From 456be106b714b3b2f5f3d43c801e28bb69fcc789 Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Thu, 3 Oct 2024 15:22:44 +0100 Subject: [PATCH] bootstrap: Consolidate editor LSP setup Consolidate LSP setup for different editors into one `./x setup editor`. --- src/bootstrap/src/core/build_steps/setup.rs | 116 ++++++++++++-------- src/bootstrap/src/core/builder.rs | 10 +- src/bootstrap/src/core/config/flags.rs | 9 +- src/bootstrap/src/utils/change_tracker.rs | 2 +- src/etc/completions/x.py.sh | 2 +- 5 files changed, 77 insertions(+), 62 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 3aa8d3a67d8bd..519649779336c 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -528,6 +528,35 @@ enum EditorKind { } impl EditorKind { + fn prompt_user() -> io::Result> { + let prompt_str = "Available editors: +1. vscode +2. vim +3. emacs +4. helix + +Select which editor you would like to set up [default: None]: "; + + let mut input = String::new(); + loop { + print!("{}", prompt_str); + io::stdout().flush()?; + input.clear(); + io::stdin().read_line(&mut input)?; + match input.trim().to_lowercase().as_str() { + "1" | "vscode" => return Ok(Some(EditorKind::Vscode)), + "2" | "vim" => return Ok(Some(EditorKind::Vim)), + "3" | "emacs" => return Ok(Some(EditorKind::Emacs)), + "4" | "helix" => return Ok(Some(EditorKind::Helix)), + "" => return Ok(None), + _ => { + eprintln!("ERROR: unrecognized option '{}'", input.trim()); + eprintln!("NOTE: press Ctrl+C to exit"); + } + }; + } + } + /// A list of historical hashes of each LSP settings file /// New entries should be appended whenever this is updated so we can detect /// outdated vs. user-modified settings files. @@ -568,10 +597,10 @@ impl EditorKind { fn settings_folder(&self) -> PathBuf { match self { - EditorKind::Vscode => PathBuf::new().join(".vscode"), - EditorKind::Vim => PathBuf::new().join(".vim"), + EditorKind::Vscode => PathBuf::from(".vscode"), + EditorKind::Vim => PathBuf::from(".vim"), EditorKind::Emacs => PathBuf::new(), - EditorKind::Helix => PathBuf::new().join(".helix"), + EditorKind::Helix => PathBuf::from(".helix"), } } @@ -590,48 +619,47 @@ impl EditorKind { } } -/// Helper macro for implementing the necessary Step to support editor LSP setup -/// The first argument must match the argument set up in `flags.rs` -/// The second argument must match the name of some `EditorKind` variant -/// After using the macro, the editor needs to be registered in `builder.rs` with describe!() -macro_rules! impl_editor_support { - ( $($editor:ident, $kind:ident),+ ) => {$( - #[doc = concat!(" Sets up or displays the LSP config for ", stringify!($editor), ".")] - #[derive(Clone, Debug, Eq, PartialEq, Hash)] - pub struct $kind; - - impl Step for $kind { - type Output = (); - const DEFAULT: bool = true; - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.alias(stringify!($editor)) - } - fn make_run(run: RunConfig<'_>) { - if run.builder.config.dry_run() { - return; - } - if let [cmd] = &run.paths[..] { - if cmd.assert_single_path().path.as_path().as_os_str() == stringify!($editor) { - run.builder.ensure($kind); - } - } +/// Sets up or displays the LSP config for one of the supported editors +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct Editor; + +impl Step for Editor { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("editor") + } + + fn make_run(run: RunConfig<'_>) { + if run.builder.config.dry_run() { + return; + } + if let [cmd] = &run.paths[..] { + if cmd.assert_single_path().path.as_path().as_os_str() == "editor" { + run.builder.ensure(Editor); } - fn run(self, builder: &Builder<'_>) -> Self::Output { - let config = &builder.config; - if config.dry_run() { - return; + } + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let config = &builder.config; + if config.dry_run() { + return; + } + match EditorKind::prompt_user() { + Ok(editor_kind) => { + if let Some(editor_kind) = editor_kind { + while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {} + } else { + println!("Ok, skipping editor setup!"); } - while !t!(create_editor_settings_maybe(config, EditorKind::$kind)) {} } + Err(e) => eprintln!("Could not determine the editor: {e}"), } - )+}; + } } -impl_editor_support!(vscode, Vscode); -impl_editor_support!(vim, Vim); -impl_editor_support!(emacs, Emacs); -impl_editor_support!(helix, Helix); - /// Create the recommended editor LSP config file for rustc development, or just print it /// If this method should be re-called, it returns `false`. fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Result { @@ -662,13 +690,11 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu ); match mismatched_settings { - Some(true) => eprintln!( - "WARNING: existing `{}` is out of date, x.py will update it", - settings_filename - ), + Some(true) => { + eprintln!("WARNING: existing `{settings_filename}` is out of date, x.py will update it") + } Some(false) => eprintln!( - "WARNING: existing `{}` has been modified by user, x.py will back it up and replace it", - settings_filename + "WARNING: existing `{settings_filename}` has been modified by user, x.py will back it up and replace it" ), _ => (), } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 67f9a3ab3edfc..abc7a22889357 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1001,15 +1001,7 @@ impl<'a> Builder<'a> { run::GenerateCompletions, ), Kind::Setup => { - describe!( - setup::Profile, - setup::Hook, - setup::Link, - setup::Vscode, - setup::Emacs, - setup::Helix, - setup::Vim - ) + describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor) } Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std), Kind::Vendor => describe!(vendor::Vendor), diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index fb27d1ebb182d..3aefe517a5be6 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -447,17 +447,14 @@ Arguments: The profile is optional and you will be prompted interactively if it is not given. The following profiles are available: {} - To only set up the git hook, VS Code config or toolchain link, you may use + To only set up the git hook, editor config or toolchain link, you may use ./x.py setup hook - ./x.py setup vscode - ./x.py setup vim - ./x.py setup emacs - ./x.py setup helix + ./x.py setup editor ./x.py setup link", Profile::all_for_help(" ").trim_end()))] Setup { /// Either the profile for `config.toml` or another setup action. /// May be omitted to set up interactively - #[arg(value_name = "|hook|vscode|vim|emacs|helix|link")] + #[arg(value_name = "|hook|editor|link")] profile: Option, }, /// Suggest a subset of tests to run, based on modified files diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index e6f5363dbf2f9..b37786496cb56 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -273,6 +273,6 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ ChangeInfo { change_id: 131075, severity: ChangeSeverity::Info, - summary: "New options for ./x setup added - ./x setup [vim|emacs|helix]", + summary: "New option `./x setup editor` added, replacing `./x setup vscode` and adding support for vim, emacs and helix.", }, ]; diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 913b0e820cb51..ba7f2c9fb5d66 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -2741,7 +2741,7 @@ _x.py() { return 0 ;; x.py__setup) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [|hook|vscode|vim|emacs|helix|link] [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [|hook|editor|link] [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0