refactor(core): remove cli feature (#6704)

This commit is contained in:
Lucas Fernandes Nogueira 2023-04-14 11:33:53 -07:00 committed by GitHub
parent 34b8f339a4
commit 09376af594
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 172 additions and 1436 deletions

7
.changes/move-cli.md Normal file
View File

@ -0,0 +1,7 @@
---
"api": patch
"tauri": patch
"tauri-utils": patch
---
Moved the `cli` feature to its own plugin in the plugins-workspace repository.

View File

@ -71,7 +71,7 @@ The code for the bundler is located in `[Tauri repo root]/tooling/bundler`, and
### Developing Tauri Core and Related Components (Rust API, Macros, Codegen, and Utils)
The code for Tauri Core is located in `[Tauri repo root]/core/tauri`, and the Rust API, Macros, and Utils are in `[Tauri repo root]/core/tauri-(api/macros/utils)`. The easiest way to test your changes is to use the `[Tauri repo root]/examples/helloworld` app. It automatically rebuilds and uses your local copy of the Tauri core packages. Just run `yarn tauri build` or `yarn tauri dev` in the helloworld app directory after making changes to test them out. To use your local changes in another project, edit its `src-tauri/Cargo.toml` file so that the `tauri` key looks like `tauri = { path = "PATH", features = [ "api-all", "cli" ] }`, where `PATH` is the relative path to `[Tauri repo root]/core/tauri`. Then, your local copy of the Tauri core packages will be rebuilt and used whenever you build that project.
The code for Tauri Core is located in `[Tauri repo root]/core/tauri`, and the Rust API, Macros, and Utils are in `[Tauri repo root]/core/tauri-(api/macros/utils)`. The easiest way to test your changes is to use the `[Tauri repo root]/examples/helloworld` app. It automatically rebuilds and uses your local copy of the Tauri core packages. Just run `yarn tauri build` or `yarn tauri dev` in the helloworld app directory after making changes to test them out. To use your local changes in another project, edit its `src-tauri/Cargo.toml` file so that the `tauri` key looks like `tauri = { path = "PATH", features = [ "api-all" ] }`, where `PATH` is the relative path to `[Tauri repo root]/core/tauri`. Then, your local copy of the Tauri core packages will be rebuilt and used whenever you build that project.
#### Building the documentation locally

View File

@ -50,7 +50,7 @@ jobs:
clippy:
- { args: '', key: 'empty' }
- {
args: '--features compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart',
args: '--features compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,updater,system-tray,windows7-compat,http-multipart',
key: 'all'
}
- { args: '--features custom-protocol', key: 'custom-protocol' }

View File

@ -76,7 +76,7 @@ jobs:
key: api-all
}
- {
args: --features compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart,
args: --features compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,updater,system-tray,windows7-compat,http-multipart,
key: all
}

View File

@ -258,17 +258,6 @@
"$ref": "#/definitions/WindowConfig"
}
},
"cli": {
"description": "The CLI configuration.",
"anyOf": [
{
"$ref": "#/definitions/CliConfig"
},
{
"type": "null"
}
]
},
"bundle": {
"description": "The bundler configuration.",
"default": {
@ -778,252 +767,6 @@
}
]
},
"CliConfig": {
"description": "describes a CLI configuration\n\nSee more: https://tauri.app/v1/api/config#cliconfig",
"type": "object",
"properties": {
"description": {
"description": "Command description which will be shown on the help information.",
"type": [
"string",
"null"
]
},
"longDescription": {
"description": "Command long description which will be shown on the help information.",
"type": [
"string",
"null"
]
},
"beforeHelp": {
"description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed before the auto-generated help information. This is often used for header information.",
"type": [
"string",
"null"
]
},
"afterHelp": {
"description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed after the auto-generated help information. This is often used to describe how to use the arguments, or caveats to be noted.",
"type": [
"string",
"null"
]
},
"args": {
"description": "List of arguments for the command",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/CliArg"
}
},
"subcommands": {
"description": "List of subcommands of this command",
"type": [
"object",
"null"
],
"additionalProperties": {
"$ref": "#/definitions/CliConfig"
}
}
},
"additionalProperties": false
},
"CliArg": {
"description": "A CLI argument definition.",
"type": "object",
"required": [
"name"
],
"properties": {
"short": {
"description": "The short version of the argument, without the preceding -.\n\nNOTE: Any leading `-` characters will be stripped, and only the first non-character will be used as the short version.",
"type": [
"string",
"null"
],
"maxLength": 1,
"minLength": 1
},
"name": {
"description": "The unique argument name",
"type": "string"
},
"description": {
"description": "The argument description which will be shown on the help information. Typically, this is a short (one line) description of the arg.",
"type": [
"string",
"null"
]
},
"longDescription": {
"description": "The argument long description which will be shown on the help information. Typically this a more detailed (multi-line) message that describes the argument.",
"type": [
"string",
"null"
]
},
"takesValue": {
"description": "Specifies that the argument takes a value at run time.\n\nNOTE: values for arguments may be specified in any of the following methods - Using a space such as -o value or --option value - Using an equals and no space such as -o=value or --option=value - Use a short and no space such as -ovalue",
"default": false,
"type": "boolean"
},
"multiple": {
"description": "Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.\n\nFor example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.\n\nNOTE: Setting this requires `takes_value` to be set to true.",
"default": false,
"type": "boolean"
},
"multipleOccurrences": {
"description": "Specifies that the argument may appear more than once. For flags, this results in the number of occurrences of the flag being recorded. For example -ddd or -d -d -d would count as three occurrences. For options or arguments that take a value, this does not affect how many values they can accept. (i.e. only one at a time is allowed)\n\nFor example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.",
"default": false,
"type": "boolean"
},
"numberOfValues": {
"description": "Specifies how many values are required to satisfy this argument. For example, if you had a `-f <file>` argument where you wanted exactly 3 'files' you would set `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided 3 and only 3 values.\n\n**NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting `multiple_occurrences = true` would allow `-f <file> <file> <file> -f <file> <file> <file>` where as *not* setting it would only allow one occurrence of this argument.\n\n**NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"possibleValues": {
"description": "Specifies a list of possible values for this argument. At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"minValues": {
"description": "Specifies the minimum number of values for this argument. For example, if you had a -f `<file>` argument where you wanted at least 2 'files', you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"maxValues": {
"description": "Specifies the maximum number of values are for this argument. For example, if you had a -f `<file>` argument where you wanted up to 3 'files', you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"required": {
"description": "Sets whether or not the argument is required by default.\n\n- Required by default means it is required, when no other conflicting rules have been evaluated - Conflicting rules take precedence over being required.",
"default": false,
"type": "boolean"
},
"requiredUnlessPresent": {
"description": "Sets an arg that override this arg's required setting i.e. this arg will be required unless this other argument is present.",
"type": [
"string",
"null"
]
},
"requiredUnlessPresentAll": {
"description": "Sets args that override this arg's required setting i.e. this arg will be required unless all these other arguments are present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiredUnlessPresentAny": {
"description": "Sets args that override this arg's required setting i.e. this arg will be required unless at least one of these other arguments are present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"conflictsWith": {
"description": "Sets a conflicting argument by name i.e. when using this argument, the following argument can't be present and vice versa.",
"type": [
"string",
"null"
]
},
"conflictsWithAll": {
"description": "The same as conflictsWith but allows specifying multiple two-way conflicts per argument.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requires": {
"description": "Tets an argument by name that is required when this one is present i.e. when using this argument, the following argument must be present.",
"type": [
"string",
"null"
]
},
"requiresAll": {
"description": "Sts multiple arguments by names that are required when this one is present i.e. when using this argument, the following arguments must be present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiresIf": {
"description": "Allows a conditional requirement with the signature [arg, value] the requirement will only become valid if `arg`'s value equals `${value}`.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiredIfEq": {
"description": "Allows specifying that an argument is required conditionally with the signature [arg, value] the requirement will only become valid if the `arg`'s value equals `${value}`.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requireEquals": {
"description": "Requires that options use the --option=val syntax i.e. an equals between the option and associated value.",
"type": [
"boolean",
"null"
]
},
"index": {
"description": "The positional argument index, starting at 1.\n\nThe index refers to position according to other positional argument. It does not define position in the argument list as a whole. When utilized with multiple=true, only the last positional argument may be defined as multiple (i.e. the one with the highest index).",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 1.0
}
},
"additionalProperties": false
},
"BundleConfig": {
"description": "Configuration for tauri-bundler.\n\nSee more: https://tauri.app/v1/api/config#bundleconfig",
"type": "object",

View File

@ -685,191 +685,6 @@ pub struct BundleConfig {
pub android: AndroidConfig,
}
/// A CLI argument definition.
#[skip_serializing_none]
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CliArg {
/// The short version of the argument, without the preceding -.
///
/// NOTE: Any leading `-` characters will be stripped, and only the first non-character will be used as the short version.
pub short: Option<char>,
/// The unique argument name
pub name: String,
/// The argument description which will be shown on the help information.
/// Typically, this is a short (one line) description of the arg.
pub description: Option<String>,
/// The argument long description which will be shown on the help information.
/// Typically this a more detailed (multi-line) message that describes the argument.
#[serde(alias = "long-description")]
pub long_description: Option<String>,
/// Specifies that the argument takes a value at run time.
///
/// NOTE: values for arguments may be specified in any of the following methods
/// - Using a space such as -o value or --option value
/// - Using an equals and no space such as -o=value or --option=value
/// - Use a short and no space such as -ovalue
#[serde(default, alias = "takes-value")]
pub takes_value: bool,
/// Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.
///
/// For example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.
///
/// NOTE: Setting this requires `takes_value` to be set to true.
#[serde(default)]
pub multiple: bool,
/// Specifies that the argument may appear more than once.
/// For flags, this results in the number of occurrences of the flag being recorded. For example -ddd or -d -d -d would count as three occurrences.
/// For options or arguments that take a value, this does not affect how many values they can accept. (i.e. only one at a time is allowed)
///
/// For example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.
#[serde(default, alias = "multiple-occurrences")]
pub multiple_occurrences: bool,
/// Specifies how many values are required to satisfy this argument. For example, if you had a
/// `-f <file>` argument where you wanted exactly 3 'files' you would set
/// `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided
/// 3 and only 3 values.
///
/// **NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting
/// `multiple_occurrences = true` would allow `-f <file> <file> <file> -f <file> <file> <file>` where
/// as *not* setting it would only allow one occurrence of this argument.
///
/// **NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.
#[serde(alias = "number-of-values")]
pub number_of_values: Option<usize>,
/// Specifies a list of possible values for this argument.
/// At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.
#[serde(alias = "possible-values")]
pub possible_values: Option<Vec<String>>,
/// Specifies the minimum number of values for this argument.
/// For example, if you had a -f `<file>` argument where you wanted at least 2 'files',
/// you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.
#[serde(alias = "min-values")]
pub min_values: Option<usize>,
/// Specifies the maximum number of values are for this argument.
/// For example, if you had a -f `<file>` argument where you wanted up to 3 'files',
/// you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.
#[serde(alias = "max-values")]
pub max_values: Option<usize>,
/// Sets whether or not the argument is required by default.
///
/// - Required by default means it is required, when no other conflicting rules have been evaluated
/// - Conflicting rules take precedence over being required.
#[serde(default)]
pub required: bool,
/// Sets an arg that override this arg's required setting
/// i.e. this arg will be required unless this other argument is present.
#[serde(alias = "required-unless-present")]
pub required_unless_present: Option<String>,
/// Sets args that override this arg's required setting
/// i.e. this arg will be required unless all these other arguments are present.
#[serde(alias = "required-unless-present-all")]
pub required_unless_present_all: Option<Vec<String>>,
/// Sets args that override this arg's required setting
/// i.e. this arg will be required unless at least one of these other arguments are present.
#[serde(alias = "required-unless-present-any")]
pub required_unless_present_any: Option<Vec<String>>,
/// Sets a conflicting argument by name
/// i.e. when using this argument, the following argument can't be present and vice versa.
#[serde(alias = "conflicts-with")]
pub conflicts_with: Option<String>,
/// The same as conflictsWith but allows specifying multiple two-way conflicts per argument.
#[serde(alias = "conflicts-with-all")]
pub conflicts_with_all: Option<Vec<String>>,
/// Tets an argument by name that is required when this one is present
/// i.e. when using this argument, the following argument must be present.
pub requires: Option<String>,
/// Sts multiple arguments by names that are required when this one is present
/// i.e. when using this argument, the following arguments must be present.
#[serde(alias = "requires-all")]
pub requires_all: Option<Vec<String>>,
/// Allows a conditional requirement with the signature [arg, value]
/// the requirement will only become valid if `arg`'s value equals `${value}`.
#[serde(alias = "requires-if")]
pub requires_if: Option<Vec<String>>,
/// Allows specifying that an argument is required conditionally with the signature [arg, value]
/// the requirement will only become valid if the `arg`'s value equals `${value}`.
#[serde(alias = "requires-if-eq")]
pub required_if_eq: Option<Vec<String>>,
/// Requires that options use the --option=val syntax
/// i.e. an equals between the option and associated value.
#[serde(alias = "requires-equals")]
pub require_equals: Option<bool>,
/// The positional argument index, starting at 1.
///
/// The index refers to position according to other positional argument.
/// It does not define position in the argument list as a whole. When utilized with multiple=true,
/// only the last positional argument may be defined as multiple (i.e. the one with the highest index).
#[cfg_attr(feature = "schema", validate(range(min = 1)))]
pub index: Option<usize>,
}
/// describes a CLI configuration
///
/// See more: https://tauri.app/v1/api/config#cliconfig
#[skip_serializing_none]
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CliConfig {
/// Command description which will be shown on the help information.
pub description: Option<String>,
/// Command long description which will be shown on the help information.
#[serde(alias = "long-description")]
pub long_description: Option<String>,
/// Adds additional help information to be displayed in addition to auto-generated help.
/// This information is displayed before the auto-generated help information.
/// This is often used for header information.
#[serde(alias = "before-help")]
pub before_help: Option<String>,
/// Adds additional help information to be displayed in addition to auto-generated help.
/// This information is displayed after the auto-generated help information.
/// This is often used to describe how to use the arguments, or caveats to be noted.
#[serde(alias = "after-help")]
pub after_help: Option<String>,
/// List of arguments for the command
pub args: Option<Vec<CliArg>>,
/// List of subcommands of this command
pub subcommands: Option<HashMap<String, CliConfig>>,
}
impl CliConfig {
/// List of arguments for the command
pub fn args(&self) -> Option<&Vec<CliArg>> {
self.args.as_ref()
}
/// List of subcommands of this command
pub fn subcommands(&self) -> Option<&HashMap<String, CliConfig>> {
self.subcommands.as_ref()
}
/// Command description which will be shown on the help information.
pub fn description(&self) -> Option<&String> {
self.description.as_ref()
}
/// Command long description which will be shown on the help information.
pub fn long_description(&self) -> Option<&String> {
self.description.as_ref()
}
/// Adds additional help information to be displayed in addition to auto-generated help.
/// This information is displayed before the auto-generated help information.
/// This is often used for header information.
pub fn before_help(&self) -> Option<&String> {
self.before_help.as_ref()
}
/// Adds additional help information to be displayed in addition to auto-generated help.
/// This information is displayed after the auto-generated help information.
/// This is often used to describe how to use the arguments, or caveats to be noted.
pub fn after_help(&self) -> Option<&String> {
self.after_help.as_ref()
}
}
/// The window configuration object.
///
/// See more: https://tauri.app/v1/api/config#windowconfig
@ -2333,8 +2148,6 @@ pub struct TauriConfig {
/// The windows configuration.
#[serde(default)]
pub windows: Vec<WindowConfig>,
/// The CLI configuration.
pub cli: Option<CliConfig>,
/// The bundler configuration.
#[serde(default)]
pub bundle: BundleConfig,
@ -2361,7 +2174,6 @@ impl TauriConfig {
pub fn all_features() -> Vec<&'static str> {
let mut features = AllowlistConfig::all_features();
features.extend(vec![
"cli",
"updater",
"system-tray",
"macos-private-api",
@ -2374,9 +2186,6 @@ impl TauriConfig {
#[allow(dead_code)]
pub fn features(&self) -> Vec<&str> {
let mut features = self.allowlist.to_features();
if self.cli.is_some() {
features.push("cli");
}
if self.updater.active {
features.push("updater");
}
@ -3271,103 +3080,6 @@ mod build {
}
}
impl ToTokens for CliArg {
fn to_tokens(&self, tokens: &mut TokenStream) {
let short = opt_lit(self.short.as_ref());
let name = str_lit(&self.name);
let description = opt_str_lit(self.description.as_ref());
let long_description = opt_str_lit(self.long_description.as_ref());
let takes_value = self.takes_value;
let multiple = self.multiple;
let multiple_occurrences = self.multiple_occurrences;
let number_of_values = opt_lit(self.number_of_values.as_ref());
let possible_values = opt_vec_str_lit(self.possible_values.as_ref());
let min_values = opt_lit(self.min_values.as_ref());
let max_values = opt_lit(self.max_values.as_ref());
let required = self.required;
let required_unless_present = opt_str_lit(self.required_unless_present.as_ref());
let required_unless_present_all = opt_vec_str_lit(self.required_unless_present_all.as_ref());
let required_unless_present_any = opt_vec_str_lit(self.required_unless_present_any.as_ref());
let conflicts_with = opt_str_lit(self.conflicts_with.as_ref());
let conflicts_with_all = opt_vec_str_lit(self.conflicts_with_all.as_ref());
let requires = opt_str_lit(self.requires.as_ref());
let requires_all = opt_vec_str_lit(self.requires_all.as_ref());
let requires_if = opt_vec_str_lit(self.requires_if.as_ref());
let required_if_eq = opt_vec_str_lit(self.required_if_eq.as_ref());
let require_equals = opt_lit(self.require_equals.as_ref());
let index = opt_lit(self.index.as_ref());
literal_struct!(
tokens,
CliArg,
short,
name,
description,
long_description,
takes_value,
multiple,
multiple_occurrences,
number_of_values,
possible_values,
min_values,
max_values,
required,
required_unless_present,
required_unless_present_all,
required_unless_present_any,
conflicts_with,
conflicts_with_all,
requires,
requires_all,
requires_if,
required_if_eq,
require_equals,
index
);
}
}
impl ToTokens for CliConfig {
fn to_tokens(&self, tokens: &mut TokenStream) {
let description = opt_str_lit(self.description.as_ref());
let long_description = opt_str_lit(self.long_description.as_ref());
let before_help = opt_str_lit(self.before_help.as_ref());
let after_help = opt_str_lit(self.after_help.as_ref());
let args = {
let args = self.args.as_ref().map(|args| {
let arg = args.iter().map(|a| quote! { #a });
quote! { vec![#(#arg),*] }
});
opt_lit(args.as_ref())
};
let subcommands = opt_lit(
self
.subcommands
.as_ref()
.map(|map| {
map_lit(
quote! { ::std::collections::HashMap },
map,
str_lit,
identity,
)
})
.as_ref(),
);
literal_struct!(
tokens,
CliConfig,
description,
long_description,
before_help,
after_help,
args,
subcommands
);
}
}
impl ToTokens for PatternKind {
fn to_tokens(&self, tokens: &mut TokenStream) {
let prefix = quote! { ::tauri::utils::config::PatternKind };
@ -3781,7 +3493,6 @@ mod build {
fn to_tokens(&self, tokens: &mut TokenStream) {
let pattern = &self.pattern;
let windows = vec_lit(&self.windows, identity);
let cli = opt_lit(self.cli.as_ref());
let bundle = &self.bundle;
let updater = &self.updater;
let security = &self.security;
@ -3794,7 +3505,6 @@ mod build {
TauriConfig,
pattern,
windows,
cli,
bundle,
updater,
security,
@ -3884,7 +3594,6 @@ mod test {
ios: Default::default(),
android: Default::default(),
},
cli: None,
updater: UpdaterConfig {
active: false,
dialog: true,

View File

@ -20,7 +20,6 @@ features = [
"custom-protocol",
"api-all",
"windows7-compat",
"cli",
"updater",
"fs-extract-api",
"system-tray",
@ -64,7 +63,6 @@ http = "0.2"
dirs-next = "2.0"
percent-encoding = "2.2"
base64 = { version = "0.21", optional = true }
clap = { version = "3", optional = true }
reqwest = { version = "0.11", default-features = false, features = [ "json", "stream" ] }
bytes = { version = "1", features = [ "serde" ] }
open = { version = "3.0", optional = true }
@ -166,7 +164,6 @@ global-shortcut = [
clipboard = [ "tauri-runtime/clipboard", "tauri-runtime-wry/clipboard" ]
dialog = [ "rfd" ]
notification = [ "notify-rust" ]
cli = [ "clap" ]
system-tray = [ "tauri-runtime/system-tray", "tauri-runtime-wry/system-tray" ]
devtools = [ "tauri-runtime/devtools", "tauri-runtime-wry/devtools" ]
dox = [ "tauri-runtime-wry/dox" ]

View File

@ -123,8 +123,6 @@ fn main() {
alias_module("http", &["request"], api_all);
alias("cli", has_feature("cli"));
if !mobile {
alias_module("notification", &[], api_all);
alias_module("global-shortcut", &[], api_all);

File diff suppressed because one or more lines are too long

View File

@ -1,283 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
//! Types and functions related to CLI arguments.
use crate::{
utils::config::{CliArg, CliConfig},
PackageInfo,
};
use clap::{Arg, ArgMatches, ErrorKind};
use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;
#[macro_use]
mod macros;
mod clapfix {
//! Compatibility between `clap` 3.0 and 3.1+ without deprecation errors.
#![allow(deprecated)]
pub type ClapCommand<'help> = clap::App<'help>;
pub trait ErrorExt {
fn kind(&self) -> clap::ErrorKind;
}
impl ErrorExt for clap::Error {
fn kind(&self) -> clap::ErrorKind {
self.kind
}
}
}
use clapfix::{ClapCommand as App, ErrorExt};
/// The resolution of a argument match.
#[derive(Default, Debug, Serialize)]
#[non_exhaustive]
pub struct ArgData {
/// - [`Value::Bool`] if it's a flag,
/// - [`Value::Array`] if it's multiple,
/// - [`Value::String`] if it has value,
/// - [`Value::Null`] otherwise.
pub value: Value,
/// The number of occurrences of the argument.
/// e.g. `./app --arg 1 --arg 2 --arg 2 3 4` results in three occurrences.
pub occurrences: u64,
}
/// The matched subcommand.
#[derive(Default, Debug, Serialize)]
#[non_exhaustive]
pub struct SubcommandMatches {
/// The subcommand name.
pub name: String,
/// The subcommand argument matches.
pub matches: Matches,
}
/// The argument matches of a command.
#[derive(Default, Debug, Serialize)]
#[non_exhaustive]
pub struct Matches {
/// Data structure mapping each found arg with its resolution.
pub args: HashMap<String, ArgData>,
/// The matched subcommand if found.
pub subcommand: Option<Box<SubcommandMatches>>,
}
impl Matches {
/// Set a arg match.
pub(crate) fn set_arg(&mut self, name: String, value: ArgData) {
self.args.insert(name, value);
}
/// Sets the subcommand matches.
pub(crate) fn set_subcommand(&mut self, name: String, matches: Matches) {
self.subcommand = Some(Box::new(SubcommandMatches { name, matches }));
}
}
/// Gets the argument matches of the CLI definition.
///
/// This is a low level API. If the application has been built,
/// prefer [`App::get_cli_matches`](`crate::App#method.get_cli_matches`).
///
/// # Examples
///
/// ```rust,no_run
/// use tauri::api::cli::get_matches;
/// tauri::Builder::default()
/// .setup(|app| {
/// let matches = get_matches(app.config().tauri.cli.as_ref().unwrap(), app.package_info())?;
/// Ok(())
/// });
/// ```
pub fn get_matches(cli: &CliConfig, package_info: &PackageInfo) -> crate::api::Result<Matches> {
let about = cli
.description()
.unwrap_or(&package_info.description.to_string())
.to_string();
let version = &*package_info.version.to_string();
let app = get_app(package_info, version, &package_info.name, Some(&about), cli);
match app.try_get_matches() {
Ok(matches) => Ok(get_matches_internal(cli, &matches)),
Err(e) => match ErrorExt::kind(&e) {
ErrorKind::DisplayHelp => {
let mut matches = Matches::default();
let help_text = e.to_string();
matches.args.insert(
"help".to_string(),
ArgData {
value: Value::String(help_text),
occurrences: 0,
},
);
Ok(matches)
}
ErrorKind::DisplayVersion => {
let mut matches = Matches::default();
matches
.args
.insert("version".to_string(), Default::default());
Ok(matches)
}
_ => Err(e.into()),
},
}
}
fn get_matches_internal(config: &CliConfig, matches: &ArgMatches) -> Matches {
let mut cli_matches = Matches::default();
map_matches(config, matches, &mut cli_matches);
if let Some((subcommand_name, subcommand_matches)) = matches.subcommand() {
if let Some(subcommand_config) = config
.subcommands
.as_ref()
.and_then(|s| s.get(subcommand_name))
{
cli_matches.set_subcommand(
subcommand_name.to_string(),
get_matches_internal(subcommand_config, subcommand_matches),
);
}
}
cli_matches
}
fn map_matches(config: &CliConfig, matches: &ArgMatches, cli_matches: &mut Matches) {
if let Some(args) = config.args() {
for arg in args {
#[allow(deprecated)]
let occurrences = matches.occurrences_of(arg.name.clone());
let value = if occurrences == 0 || !arg.takes_value {
Value::Bool(occurrences > 0)
} else if arg.multiple {
#[allow(deprecated)]
matches
.values_of(arg.name.clone())
.map(|v| {
let mut values = Vec::new();
for value in v {
values.push(Value::String(value.to_string()));
}
Value::Array(values)
})
.unwrap_or(Value::Null)
} else {
#[allow(deprecated)]
matches
.value_of(arg.name.clone())
.map(|v| Value::String(v.to_string()))
.unwrap_or(Value::Null)
};
cli_matches.set_arg(arg.name.clone(), ArgData { value, occurrences });
}
}
}
fn get_app<'a>(
package_info: &'a PackageInfo,
version: &'a str,
command_name: &'a str,
about: Option<&'a String>,
config: &'a CliConfig,
) -> App<'a> {
let mut app = App::new(command_name)
.author(package_info.authors)
.version(version);
if let Some(about) = about {
app = app.about(&**about);
}
if let Some(long_description) = config.long_description() {
app = app.long_about(&**long_description);
}
if let Some(before_help) = config.before_help() {
app = app.before_help(&**before_help);
}
if let Some(after_help) = config.after_help() {
app = app.after_help(&**after_help);
}
if let Some(args) = config.args() {
for arg in args {
let arg_name = arg.name.as_ref();
app = app.arg(get_arg(arg_name, arg));
}
}
if let Some(subcommands) = config.subcommands() {
for (subcommand_name, subcommand) in subcommands {
let clap_subcommand = get_app(
package_info,
version,
subcommand_name,
subcommand.description(),
subcommand,
);
app = app.subcommand(clap_subcommand);
}
}
app
}
fn get_arg<'a>(arg_name: &'a str, arg: &'a CliArg) -> Arg<'a> {
let mut clap_arg = Arg::new(arg_name);
if arg.index.is_none() {
clap_arg = clap_arg.long(arg_name);
if let Some(short) = arg.short {
clap_arg = clap_arg.short(short);
}
}
clap_arg = bind_string_arg!(arg, clap_arg, description, help);
clap_arg = bind_string_arg!(arg, clap_arg, long_description, long_help);
clap_arg = clap_arg.takes_value(arg.takes_value);
clap_arg = clap_arg.multiple_values(arg.multiple);
#[allow(deprecated)]
{
clap_arg = clap_arg.multiple_occurrences(arg.multiple_occurrences);
}
clap_arg = bind_value_arg!(arg, clap_arg, number_of_values);
#[allow(deprecated)]
{
clap_arg = bind_string_slice_arg!(arg, clap_arg, possible_values);
}
clap_arg = bind_value_arg!(arg, clap_arg, min_values);
clap_arg = bind_value_arg!(arg, clap_arg, max_values);
clap_arg = clap_arg.required(arg.required);
clap_arg = bind_string_arg!(
arg,
clap_arg,
required_unless_present,
required_unless_present
);
clap_arg = bind_string_slice_arg!(arg, clap_arg, required_unless_present_all);
clap_arg = bind_string_slice_arg!(arg, clap_arg, required_unless_present_any);
clap_arg = bind_string_arg!(arg, clap_arg, conflicts_with, conflicts_with);
if let Some(value) = &arg.conflicts_with_all {
let v: Vec<&str> = value.iter().map(|x| &**x).collect();
clap_arg = clap_arg.conflicts_with_all(&v);
}
clap_arg = bind_string_arg!(arg, clap_arg, requires, requires);
if let Some(value) = &arg.requires_all {
let v: Vec<&str> = value.iter().map(|x| &**x).collect();
clap_arg = clap_arg.requires_all(&v);
}
clap_arg = bind_if_arg!(arg, clap_arg, requires_if);
clap_arg = bind_if_arg!(arg, clap_arg, required_if_eq);
clap_arg = bind_value_arg!(arg, clap_arg, require_equals);
clap_arg = bind_value_arg!(arg, clap_arg, index);
clap_arg
}

View File

@ -1,49 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
macro_rules! bind_string_arg {
($arg:expr, $clap_arg:expr, $arg_name:ident, $clap_field:ident) => {{
let arg = $arg;
let mut clap_arg = $clap_arg;
if let Some(value) = &arg.$arg_name {
clap_arg = clap_arg.$clap_field(value.as_str());
}
clap_arg
}};
}
macro_rules! bind_value_arg {
($arg:expr, $clap_arg:expr, $field:ident) => {{
let arg = $arg;
let mut clap_arg = $clap_arg;
if let Some(value) = arg.$field {
clap_arg = clap_arg.$field(value);
}
clap_arg
}};
}
macro_rules! bind_string_slice_arg {
($arg:expr, $clap_arg:expr, $field:ident) => {{
let arg = $arg;
let mut clap_arg = $clap_arg;
if let Some(value) = &arg.$field {
let v: Vec<&str> = value.iter().map(|x| &**x).collect();
clap_arg = clap_arg.$field(v);
}
clap_arg
}};
}
macro_rules! bind_if_arg {
($arg:expr, $clap_arg:expr, $field:ident) => {{
let arg = $arg;
let mut clap_arg = $clap_arg;
if let Some(value) = &arg.$field {
let v: Vec<&str> = value.iter().map(|x| &**x).collect();
clap_arg = clap_arg.$field(&v[0], &v[1]);
}
clap_arg
}};
}

View File

@ -69,11 +69,6 @@ pub enum Error {
/// failed to detect the current platform.
#[error("failed to detect platform: {0}")]
FailedToDetectPlatform(String),
/// CLI argument parsing error.
#[cfg(feature = "cli")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "cli")))]
#[error("failed to parse CLI arguments: {0}")]
ParseCliArguments(String),
/// Shell error.
#[error("shell error: {0}")]
Shell(String),
@ -84,10 +79,3 @@ pub enum Error {
#[error(transparent)]
Http(#[from] http::Error),
}
#[cfg(feature = "cli")]
impl From<clap::Error> for Error {
fn from(error: clap::Error) -> Self {
Self::ParseCliArguments(error.to_string())
}
}

View File

@ -19,14 +19,6 @@ pub mod process;
pub mod shell;
pub mod version;
#[cfg(feature = "cli")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "cli")))]
pub mod cli;
#[cfg(feature = "cli")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "cli")))]
pub use clap;
#[cfg(all(desktop, feature = "notification"))]
#[cfg_attr(doc_cfg, doc(cfg(all(desktop, feature = "notification"))))]
pub mod notification;

View File

@ -748,26 +748,6 @@ impl<R: Runtime> App<R> {
.set_device_event_filter(filter);
}
/// Gets the argument matches of the CLI definition configured in `tauri.conf.json`.
///
/// # Examples
///
/// ```
/// tauri::Builder::default()
/// .setup(|app| {
/// let matches = app.get_cli_matches()?;
/// Ok(())
/// });
/// ```
#[cfg(cli)]
pub fn get_cli_matches(&self) -> crate::Result<crate::api::cli::Matches> {
if let Some(cli) = &self.manager.config().tauri.cli {
crate::api::cli::get_matches(cli, self.manager.package_info()).map_err(Into::into)
} else {
Ok(Default::default())
}
}
/// Runs the application.
///
/// # Examples

View File

@ -13,8 +13,6 @@ use serde_json::Value as JsonValue;
use std::sync::Arc;
mod app;
#[cfg(cli)]
mod cli;
#[cfg(clipboard_any)]
mod clipboard;
#[cfg(dialog_any)]
@ -82,8 +80,6 @@ enum Module {
Event(event::Cmd),
#[cfg(dialog_any)]
Dialog(dialog::Cmd),
#[cfg(cli)]
Cli(cli::Cmd),
Notification(notification::Cmd),
#[cfg(http_any)]
Http(http::Cmd),
@ -161,13 +157,6 @@ impl Module {
.and_then(|r| r.json)
.map_err(InvokeError::from_anyhow)
}),
#[cfg(cli)]
Self::Cli(cmd) => resolver.respond_async(async move {
cmd
.run(context)
.and_then(|r| r.json)
.map_err(InvokeError::from_anyhow)
}),
Self::Notification(cmd) => resolver.respond_async(async move {
cmd
.run(context)

View File

@ -1,47 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![allow(unused_imports)]
use super::{InvokeContext, InvokeResponse};
use crate::Runtime;
use serde::Deserialize;
use tauri_macros::{command_enum, module_command_handler, CommandModule};
/// The API descriptor.
#[command_enum]
#[derive(CommandModule, Deserialize)]
#[serde(tag = "cmd", rename_all = "camelCase")]
pub enum Cmd {
/// The get CLI matches API.
CliMatches,
}
impl Cmd {
#[module_command_handler(cli)]
fn cli_matches<R: Runtime>(context: InvokeContext<R>) -> super::Result<InvokeResponse> {
if let Some(cli) = &context.config.tauri.cli {
crate::api::cli::get_matches(cli, &context.package_info)
.map(Into::into)
.map_err(Into::into)
} else {
Ok(crate::api::cli::Matches::default().into())
}
}
#[cfg(not(cli))]
fn cli_matches<R: Runtime>(_: InvokeContext<R>) -> super::Result<InvokeResponse> {
Err(crate::error::into_anyhow("CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.app/docs/api/config#tauri.cli)"))
}
}
#[cfg(test)]
mod tests {
#[tauri_macros::module_command_test(cli, "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.app/docs/api/config#tauri.cli)", runtime)]
#[quickcheck_macros::quickcheck]
fn cli_matches() {
let res = super::Cmd::cli_matches(crate::test::mock_invoke_context());
crate::test_utils::assert_not_allowlist_error(res);
}
}

View File

@ -32,7 +32,6 @@
//! - **dialog**: Enables the [`api::dialog`] module.
//! - **notification**: Enables the [`api::notification`] module.
//! - **fs-extract-api**: Enabled the `tauri::api::file::Extract` API.
//! - **cli**: Enables usage of `clap` for CLI argument parsing. Enabled by default if the `cli` config is defined on the `tauri.conf.json` file.
//! - **system-tray**: Enables application system tray API. Enabled by default if the `systemTray` config is defined on the `tauri.conf.json` file.
//! - **macos-private-api**: Enables features only available in **macOS**'s private APIs, currently the `transparent` window functionality and the `fullScreenEnabled` preference setting to `true`. Enabled by default if the `tauri > macosPrivateApi` config flag is set to `true` on the `tauri.conf.json` file.
//! - **windows7-compat**: Enables compatibility with Windows 7 for the notification API.

View File

@ -16,7 +16,7 @@ use crate::ShellScopeConfig;
use crate::{Manager, Pattern, WindowBuilder};
use tauri_utils::{
assets::{AssetKey, Assets, CspHash},
config::{CliConfig, Config, PatternKind, TauriConfig, WindowUrl},
config::{Config, PatternKind, TauriConfig, WindowUrl},
};
pub struct NoopAsset {
@ -47,14 +47,6 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
tauri: TauriConfig {
pattern: PatternKind::Brownfield,
windows: Vec::new(),
cli: Some(CliConfig {
description: None,
long_description: None,
before_help: None,
after_help: None,
args: None,
subcommands: None,
}),
bundle: Default::default(),
allowlist: Default::default(),
security: Default::default(),

File diff suppressed because one or more lines are too long

View File

@ -67,6 +67,55 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "anstream"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anstyle-parse"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "anstyle-wincon"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
]
[[package]]
name = "anyhow"
version = "1.0.69"
@ -82,6 +131,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-cli",
"tauri-plugin-sample",
"tiny_http",
"window-shadows",
@ -227,17 +277,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "debc29dde2e69f9e47506b525f639ed42300fc014a3e007832592448fa8e4599"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -440,27 +479,31 @@ dependencies = [
[[package]]
name = "clap"
version = "3.2.23"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a"
dependencies = [
"atty",
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6"
dependencies = [
"anstream",
"anstyle",
"bitflags",
"clap_lex",
"indexmap",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
[[package]]
name = "cocoa"
@ -499,6 +542,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "combine"
version = "4.6.6"
@ -1382,15 +1431,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
@ -1619,6 +1659,18 @@ version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
]
[[package]]
name = "itoa"
version = "0.4.8"
@ -2164,12 +2216,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "overload"
version = "0.1.1"
@ -3227,12 +3273,11 @@ dependencies = [
[[package]]
name = "tauri"
version = "2.0.0-alpha.6"
version = "2.0.0-alpha.8"
dependencies = [
"anyhow",
"base64 0.21.0",
"bytes",
"clap",
"cocoa",
"dirs-next",
"embed_plist",
@ -3293,7 +3338,7 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.0.0-alpha.3"
version = "2.0.0-alpha.4"
dependencies = [
"anyhow",
"cargo_toml",
@ -3313,7 +3358,7 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "2.0.0-alpha.3"
version = "2.0.0-alpha.4"
dependencies = [
"base64 0.21.0",
"brotli",
@ -3338,7 +3383,7 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "2.0.0-alpha.3"
version = "2.0.0-alpha.4"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@ -3348,6 +3393,19 @@ dependencies = [
"tauri-utils",
]
[[package]]
name = "tauri-plugin-cli"
version = "0.1.0"
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=next#0fed10fdcebf659458859c820d1d386a8c136327"
dependencies = [
"clap",
"log",
"serde",
"serde_json",
"tauri",
"thiserror",
]
[[package]]
name = "tauri-plugin-sample"
version = "0.1.0"
@ -3361,7 +3419,7 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "0.13.0-alpha.3"
version = "0.13.0-alpha.4"
dependencies = [
"gtk",
"http",
@ -3381,7 +3439,7 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "0.13.0-alpha.3"
version = "0.13.0-alpha.4"
dependencies = [
"cocoa",
"gtk",
@ -3400,7 +3458,7 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "2.0.0-alpha.3"
version = "2.0.0-alpha.4"
dependencies = [
"aes-gcm",
"brotli",
@ -3473,21 +3531,6 @@ dependencies = [
"utf-8",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thin-slice"
version = "0.1.1"
@ -3804,6 +3847,12 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.3.0"

View File

@ -19,6 +19,7 @@ tiny_http = "0.11"
log = "0.4"
#tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-sample = { path = "./tauri-plugin-sample/" }
tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
[patch.crates-io]
tauri = { path = "../../../core/tauri" }
@ -28,7 +29,6 @@ tauri-build = { path = "../../../core/tauri-build" }
path = "../../../core/tauri"
features = [
"api-all",
"cli",
"global-shortcut",
"http-multipart",
"icon-ico",

View File

@ -33,6 +33,7 @@ pub fn run() {
.build(),
)*/
.plugin(tauri_plugin_sample::init())
.plugin(tauri_plugin_cli::init())
.setup(move |app| {
#[cfg(desktop)]
tray::create_tray(app)?;

View File

@ -11,14 +11,7 @@
"productName": "Tauri API",
"version": "1.0.0"
},
"tauri": {
"pattern": {
"use": "isolation",
"options": {
"dir": "../isolation-dist/"
}
},
"macOSPrivateApi": true,
"plugins": {
"cli": {
"description": "Tauri API example",
"args": [
@ -33,7 +26,11 @@
"name": "theme",
"takesValue": true,
"description": "App theme",
"possibleValues": ["light", "dark", "system"]
"possibleValues": [
"light",
"dark",
"system"
]
},
{
"short": "v",
@ -54,7 +51,16 @@
]
}
}
}
},
"tauri": {
"pattern": {
"use": "isolation",
"options": {
"dir": "../isolation-dist/"
}
},
"macOSPrivateApi": true,
"bundle": {
"active": true,
"identifier": "com.tauri.api",

View File

@ -1,10 +1,10 @@
<script>
import { getMatches } from '@tauri-apps/api/cli'
import { invoke } from '@tauri-apps/api/tauri'
export let onMessage
function cliMatches() {
getMatches().then(onMessage).catch(onMessage)
invoke('plugin:cli|cli_matches').then(onMessage).catch(onMessage)
}
</script>

File diff suppressed because one or more lines are too long

View File

@ -1,77 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
/**
* Parse arguments from your Command Line Interface.
*
* This package is also accessible with `window.__TAURI__.cli` when [`build.withGlobalTauri`](https://tauri.app/v1/api/config/#buildconfig.withglobaltauri) in `tauri.conf.json` is set to `true`.
* @module
*/
import { invokeTauriCommand } from './helpers/tauri'
/**
* @since 1.0.0
*/
interface ArgMatch {
/**
* string if takes value
* boolean if flag
* string[] or null if takes multiple values
*/
value: string | boolean | string[] | null
/**
* Number of occurrences
*/
occurrences: number
}
/**
* @since 1.0.0
*/
interface SubcommandMatch {
name: string
matches: CliMatches
}
/**
* @since 1.0.0
*/
interface CliMatches {
args: Record<string, ArgMatch>
subcommand: SubcommandMatch | null
}
/**
* Parse the arguments provided to the current process and get the matches using the configuration defined [`tauri.cli`](https://tauri.app/v1/api/config/#tauriconfig.cli) in `tauri.conf.json`
* @example
* ```typescript
* import { getMatches } from '@tauri-apps/api/cli';
* const matches = await getMatches();
* if (matches.subcommand?.name === 'run') {
* // `./your-app run $ARGS` was executed
* const args = matches.subcommand?.matches.args
* if ('debug' in args) {
* // `./your-app run --debug` was executed
* }
* } else {
* const args = matches.args
* // `./your-app $ARGS` was executed
* }
* ```
*
* @since 1.0.0
*/
async function getMatches(): Promise<CliMatches> {
return invokeTauriCommand<CliMatches>({
__tauriModule: 'Cli',
message: {
cmd: 'cliMatches'
}
})
}
export type { ArgMatch, SubcommandMatch, CliMatches }
export { getMatches }

View File

@ -14,7 +14,6 @@
*/
import * as app from './app'
import * as cli from './cli'
import * as clipboard from './clipboard'
import * as dialog from './dialog'
import * as event from './event'
@ -36,7 +35,6 @@ const invoke = tauri.invoke
export {
invoke,
app,
cli,
clipboard,
dialog,
event,

View File

@ -258,17 +258,6 @@
"$ref": "#/definitions/WindowConfig"
}
},
"cli": {
"description": "The CLI configuration.",
"anyOf": [
{
"$ref": "#/definitions/CliConfig"
},
{
"type": "null"
}
]
},
"bundle": {
"description": "The bundler configuration.",
"default": {
@ -778,252 +767,6 @@
}
]
},
"CliConfig": {
"description": "describes a CLI configuration\n\nSee more: https://tauri.app/v1/api/config#cliconfig",
"type": "object",
"properties": {
"description": {
"description": "Command description which will be shown on the help information.",
"type": [
"string",
"null"
]
},
"longDescription": {
"description": "Command long description which will be shown on the help information.",
"type": [
"string",
"null"
]
},
"beforeHelp": {
"description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed before the auto-generated help information. This is often used for header information.",
"type": [
"string",
"null"
]
},
"afterHelp": {
"description": "Adds additional help information to be displayed in addition to auto-generated help. This information is displayed after the auto-generated help information. This is often used to describe how to use the arguments, or caveats to be noted.",
"type": [
"string",
"null"
]
},
"args": {
"description": "List of arguments for the command",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/CliArg"
}
},
"subcommands": {
"description": "List of subcommands of this command",
"type": [
"object",
"null"
],
"additionalProperties": {
"$ref": "#/definitions/CliConfig"
}
}
},
"additionalProperties": false
},
"CliArg": {
"description": "A CLI argument definition.",
"type": "object",
"required": [
"name"
],
"properties": {
"short": {
"description": "The short version of the argument, without the preceding -.\n\nNOTE: Any leading `-` characters will be stripped, and only the first non-character will be used as the short version.",
"type": [
"string",
"null"
],
"maxLength": 1,
"minLength": 1
},
"name": {
"description": "The unique argument name",
"type": "string"
},
"description": {
"description": "The argument description which will be shown on the help information. Typically, this is a short (one line) description of the arg.",
"type": [
"string",
"null"
]
},
"longDescription": {
"description": "The argument long description which will be shown on the help information. Typically this a more detailed (multi-line) message that describes the argument.",
"type": [
"string",
"null"
]
},
"takesValue": {
"description": "Specifies that the argument takes a value at run time.\n\nNOTE: values for arguments may be specified in any of the following methods - Using a space such as -o value or --option value - Using an equals and no space such as -o=value or --option=value - Use a short and no space such as -ovalue",
"default": false,
"type": "boolean"
},
"multiple": {
"description": "Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.\n\nFor example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.\n\nNOTE: Setting this requires `takes_value` to be set to true.",
"default": false,
"type": "boolean"
},
"multipleOccurrences": {
"description": "Specifies that the argument may appear more than once. For flags, this results in the number of occurrences of the flag being recorded. For example -ddd or -d -d -d would count as three occurrences. For options or arguments that take a value, this does not affect how many values they can accept. (i.e. only one at a time is allowed)\n\nFor example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.",
"default": false,
"type": "boolean"
},
"numberOfValues": {
"description": "Specifies how many values are required to satisfy this argument. For example, if you had a `-f <file>` argument where you wanted exactly 3 'files' you would set `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided 3 and only 3 values.\n\n**NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting `multiple_occurrences = true` would allow `-f <file> <file> <file> -f <file> <file> <file>` where as *not* setting it would only allow one occurrence of this argument.\n\n**NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"possibleValues": {
"description": "Specifies a list of possible values for this argument. At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"minValues": {
"description": "Specifies the minimum number of values for this argument. For example, if you had a -f `<file>` argument where you wanted at least 2 'files', you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"maxValues": {
"description": "Specifies the maximum number of values are for this argument. For example, if you had a -f `<file>` argument where you wanted up to 3 'files', you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0.0
},
"required": {
"description": "Sets whether or not the argument is required by default.\n\n- Required by default means it is required, when no other conflicting rules have been evaluated - Conflicting rules take precedence over being required.",
"default": false,
"type": "boolean"
},
"requiredUnlessPresent": {
"description": "Sets an arg that override this arg's required setting i.e. this arg will be required unless this other argument is present.",
"type": [
"string",
"null"
]
},
"requiredUnlessPresentAll": {
"description": "Sets args that override this arg's required setting i.e. this arg will be required unless all these other arguments are present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiredUnlessPresentAny": {
"description": "Sets args that override this arg's required setting i.e. this arg will be required unless at least one of these other arguments are present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"conflictsWith": {
"description": "Sets a conflicting argument by name i.e. when using this argument, the following argument can't be present and vice versa.",
"type": [
"string",
"null"
]
},
"conflictsWithAll": {
"description": "The same as conflictsWith but allows specifying multiple two-way conflicts per argument.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requires": {
"description": "Tets an argument by name that is required when this one is present i.e. when using this argument, the following argument must be present.",
"type": [
"string",
"null"
]
},
"requiresAll": {
"description": "Sts multiple arguments by names that are required when this one is present i.e. when using this argument, the following arguments must be present.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiresIf": {
"description": "Allows a conditional requirement with the signature [arg, value] the requirement will only become valid if `arg`'s value equals `${value}`.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requiredIfEq": {
"description": "Allows specifying that an argument is required conditionally with the signature [arg, value] the requirement will only become valid if the `arg`'s value equals `${value}`.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"requireEquals": {
"description": "Requires that options use the --option=val syntax i.e. an equals between the option and associated value.",
"type": [
"boolean",
"null"
]
},
"index": {
"description": "The positional argument index, starting at 1.\n\nThe index refers to position according to other positional argument. It does not define position in the argument list as a whole. When utilized with multiple=true, only the last positional argument may be defined as multiple (i.e. the one with the highest index).",
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 1.0
}
},
"additionalProperties": false
},
"BundleConfig": {
"description": "Configuration for tauri-bundler.\n\nSee more: https://tauri.app/v1/api/config#bundleconfig",
"type": "object",