completions.rs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use crate::Result;
  5. use anyhow::Context;
  6. use clap::{Command, Parser};
  7. use clap_complete::{generate, Shell};
  8. use log::info;
  9. use std::{fs::write, path::PathBuf};
  10. const PKG_MANAGERS: &[&str] = &["cargo", "pnpm", "npm", "yarn"];
  11. #[derive(Debug, Clone, Parser)]
  12. #[clap(about = "Shell completions")]
  13. pub struct Options {
  14. /// Shell to generate a completion script for.
  15. #[clap(short, long, verbatim_doc_comment)]
  16. shell: Shell,
  17. /// Output file for the shell completions. By default the completions are printed to stdout.
  18. #[clap(short, long)]
  19. output: Option<PathBuf>,
  20. }
  21. fn completions_for(shell: Shell, manager: &'static str, cmd: Command) -> Vec<u8> {
  22. let tauri = cmd.name("tauri");
  23. let mut command = if manager == "npm" {
  24. Command::new(manager)
  25. .bin_name(manager)
  26. .subcommand(Command::new("run").subcommand(tauri))
  27. } else {
  28. Command::new(manager).bin_name(manager).subcommand(tauri)
  29. };
  30. let mut buf = Vec::new();
  31. generate(shell, &mut command, manager, &mut buf);
  32. buf
  33. }
  34. fn get_completions(shell: Shell, cmd: Command) -> Result<String> {
  35. let completions = if shell == Shell::Bash {
  36. let mut completions =
  37. String::from_utf8_lossy(&completions_for(shell, "cargo", cmd)).into_owned();
  38. for manager in PKG_MANAGERS {
  39. completions.push_str(&format!(
  40. "complete -F _cargo -o bashdefault -o default {} tauri\n",
  41. if manager == &"npm" {
  42. "npm run"
  43. } else {
  44. manager
  45. }
  46. ));
  47. }
  48. completions
  49. } else {
  50. let mut buffer = String::new();
  51. for (i, manager) in PKG_MANAGERS.iter().enumerate() {
  52. let buf = String::from_utf8_lossy(&completions_for(shell, manager, cmd.clone())).into_owned();
  53. let completions = match shell {
  54. Shell::PowerShell => {
  55. if i != 0 {
  56. // namespaces have already been imported
  57. buf
  58. .replace("using namespace System.Management.Automation.Language", "")
  59. .replace("using namespace System.Management.Automation", "")
  60. } else {
  61. buf
  62. }
  63. }
  64. _ => buf,
  65. };
  66. buffer.push_str(&completions);
  67. buffer.push('\n');
  68. }
  69. buffer
  70. };
  71. Ok(completions)
  72. }
  73. pub fn command(options: Options, cmd: Command) -> Result<()> {
  74. info!("Generating completion file for {}...", options.shell);
  75. let completions = get_completions(options.shell, cmd)?;
  76. if let Some(output) = options.output {
  77. write(output, completions).context("failed to write to output path")?;
  78. } else {
  79. print!("{completions}");
  80. }
  81. Ok(())
  82. }