toml: add exec.shell
This commit is contained in:
parent
b25e7554f7
commit
325f4ea71b
4 changed files with 100 additions and 17 deletions
|
|
@ -16,6 +16,7 @@ use {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
indexmap::IndexMap,
|
indexmap::IndexMap,
|
||||||
|
std::sync::LazyLock,
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -31,6 +32,12 @@ pub enum ExecParserError {
|
||||||
Env(#[from] EnvParserError),
|
Env(#[from] EnvParserError),
|
||||||
#[error("Array cannot be empty")]
|
#[error("Array cannot be empty")]
|
||||||
Empty,
|
Empty,
|
||||||
|
#[error("Exactly one of the `prog` or `shell` fields must be specified")]
|
||||||
|
ProgXorShell,
|
||||||
|
#[error("Could not read $SHELL")]
|
||||||
|
ShellNotDefined,
|
||||||
|
#[error("The `args` field cannot be used for shell commands")]
|
||||||
|
ArgsForShell,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExecParser<'a>(pub &'a Context<'a>);
|
pub struct ExecParser<'a>(pub &'a Context<'a>);
|
||||||
|
|
@ -72,16 +79,33 @@ impl Parser for ExecParser<'_> {
|
||||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||||
) -> ParseResult<Self> {
|
) -> ParseResult<Self> {
|
||||||
let mut ext = Extractor::new(self.0, span, table);
|
let mut ext = Extractor::new(self.0, span, table);
|
||||||
let (prog, args_val, envs_val, privileged) = ext.extract((
|
let (prog_opt, shell_opt, args_val, envs_val, privileged) = ext.extract((
|
||||||
str("prog"),
|
opt(str("prog")),
|
||||||
|
opt(str("shell")),
|
||||||
opt(arr("args")),
|
opt(arr("args")),
|
||||||
opt(val("env")),
|
opt(val("env")),
|
||||||
recover(opt(bol("privileged"))),
|
recover(opt(bol("privileged"))),
|
||||||
))?;
|
))?;
|
||||||
|
let prog;
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
if let Some(args_val) = args_val {
|
match (prog_opt, shell_opt) {
|
||||||
for arg in args_val.value {
|
(None, None) | (Some(_), Some(_)) => {
|
||||||
args.push(arg.parse_map(&mut StringParser)?);
|
return Err(ExecParserError::ProgXorShell.spanned(span));
|
||||||
|
}
|
||||||
|
(Some(v), _) => {
|
||||||
|
prog = v.value.to_string();
|
||||||
|
if let Some(args_val) = args_val {
|
||||||
|
for arg in args_val.value {
|
||||||
|
args.push(arg.parse_map(&mut StringParser)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(_, Some(v)) => {
|
||||||
|
prog = shell(v.span)?;
|
||||||
|
args = vec!["-c".to_string(), v.value.to_string()];
|
||||||
|
if let Some(v) = args_val {
|
||||||
|
return Err(ExecParserError::ArgsForShell.spanned(v.span));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let envs = match envs_val {
|
let envs = match envs_val {
|
||||||
|
|
@ -89,10 +113,17 @@ impl Parser for ExecParser<'_> {
|
||||||
Some(e) => e.parse_map(&mut EnvParser)?,
|
Some(e) => e.parse_map(&mut EnvParser)?,
|
||||||
};
|
};
|
||||||
Ok(Exec {
|
Ok(Exec {
|
||||||
prog: prog.value.to_string(),
|
prog,
|
||||||
args,
|
args,
|
||||||
envs,
|
envs,
|
||||||
privileged: privileged.despan().unwrap_or(false),
|
privileged: privileged.despan().unwrap_or(false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shell(span: Span) -> Result<String, Spanned<ExecParserError>> {
|
||||||
|
static SHELL: LazyLock<Option<String>> = LazyLock::new(|| std::env::var("SHELL").ok());
|
||||||
|
SHELL
|
||||||
|
.clone()
|
||||||
|
.ok_or(ExecParserError::ShellNotDefined.spanned(span))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1200,7 +1200,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Exec": {
|
"Exec": {
|
||||||
"description": "Describes how to execute a program.\n\n- Example 1:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = \"alacritty\" }\n ```\n\n- Example 2:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = [\"notify-send\", \"hello world\"] }\n ```\n\n- Example 3:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { prog = \"notify-send\", args = [\"hello world\"], env.WAYLAND_DISPLAY = \"2\" } }\n ```\n",
|
"description": "Describes how to execute a program.\n\n- Example 1:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = \"alacritty\" }\n ```\n\n- Example 2:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = [\"notify-send\", \"hello world\"] }\n ```\n\n- Example 3:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { prog = \"notify-send\", args = [\"hello world\"], env.WAYLAND_DISPLAY = \"2\" } }\n ```\n\n- Example 4:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { shell = \"grim - | wl-copy\", privileged = true } }\n ```\n",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
@ -1215,16 +1215,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "The name, arguments, and environment variables of the executable to execute.\n\n- Example:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { prog = \"notify-send\", args = [\"hello world\"], env.WAYLAND_DISPLAY = \"2\" } }\n ```\n",
|
"description": "The name, arguments, and environment variables of the executable to execute.\n\nExactly one of the `prog` or `shell` fields must be specified.\n\n- Example 1:\n\n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { prog = \"notify-send\", args = [\"hello world\"], env.WAYLAND_DISPLAY = \"2\" } }\n ```\n\n- Example 2:\n \n ```toml\n [shortcuts]\n ctrl-a = { type = \"exec\", exec = { shell = \"grim - | wl-copy\", privileged = true } }\n ```\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"prog": {
|
"prog": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the executable."
|
"description": "The name of the executable."
|
||||||
},
|
},
|
||||||
|
"shell": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of a shell command to execute. The command will be executed as\n`$SHELL -c \"command\"`.\n"
|
||||||
|
},
|
||||||
"args": {
|
"args": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "The arguments to pass to the executable.",
|
"description": "The arguments to pass to the executable.\n\nThis field must not be specified if a shell command is used.\n",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": ""
|
"description": ""
|
||||||
|
|
@ -1243,9 +1247,7 @@
|
||||||
"description": "If `true`, the executable gets access to privileged wayland protocols.\n\nThe default is `false`.\n"
|
"description": "If `true`, the executable gets access to privileged wayland protocols.\n\nThe default is `false`.\n"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": []
|
||||||
"prog"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2483,6 +2483,13 @@ Describes how to execute a program.
|
||||||
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Example 4:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
ctrl-a = { type = "exec", exec = { shell = "grim - | wl-copy", privileged = true } }
|
||||||
|
```
|
||||||
|
|
||||||
Values of this type should have one of the following forms:
|
Values of this type should have one of the following forms:
|
||||||
|
|
||||||
#### A string
|
#### A string
|
||||||
|
|
@ -2513,24 +2520,42 @@ Each element of this array should be a string.
|
||||||
|
|
||||||
The name, arguments, and environment variables of the executable to execute.
|
The name, arguments, and environment variables of the executable to execute.
|
||||||
|
|
||||||
- Example:
|
Exactly one of the `prog` or `shell` fields must be specified.
|
||||||
|
|
||||||
|
- Example 1:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[shortcuts]
|
[shortcuts]
|
||||||
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Example 2:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
ctrl-a = { type = "exec", exec = { shell = "grim - | wl-copy", privileged = true } }
|
||||||
|
```
|
||||||
|
|
||||||
The table has the following fields:
|
The table has the following fields:
|
||||||
|
|
||||||
- `prog` (required):
|
- `prog` (optional):
|
||||||
|
|
||||||
The name of the executable.
|
The name of the executable.
|
||||||
|
|
||||||
The value of this field should be a string.
|
The value of this field should be a string.
|
||||||
|
|
||||||
|
- `shell` (optional):
|
||||||
|
|
||||||
|
The name of a shell command to execute. The command will be executed as
|
||||||
|
`$SHELL -c "command"`.
|
||||||
|
|
||||||
|
The value of this field should be a string.
|
||||||
|
|
||||||
- `args` (optional):
|
- `args` (optional):
|
||||||
|
|
||||||
The arguments to pass to the executable.
|
The arguments to pass to the executable.
|
||||||
|
|
||||||
|
This field must not be specified if a shell command is used.
|
||||||
|
|
||||||
The value of this field should be an array of strings.
|
The value of this field should be an array of strings.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -733,6 +733,13 @@ Exec:
|
||||||
[shortcuts]
|
[shortcuts]
|
||||||
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Example 4:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
ctrl-a = { type = "exec", exec = { shell = "grim - | wl-copy", privileged = true } }
|
||||||
|
```
|
||||||
kind: variable
|
kind: variable
|
||||||
variants:
|
variants:
|
||||||
- kind: string
|
- kind: string
|
||||||
|
|
@ -760,24 +767,42 @@ Exec:
|
||||||
- kind: table
|
- kind: table
|
||||||
description: |
|
description: |
|
||||||
The name, arguments, and environment variables of the executable to execute.
|
The name, arguments, and environment variables of the executable to execute.
|
||||||
|
|
||||||
|
Exactly one of the `prog` or `shell` fields must be specified.
|
||||||
|
|
||||||
- Example:
|
- Example 1:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[shortcuts]
|
[shortcuts]
|
||||||
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
ctrl-a = { type = "exec", exec = { prog = "notify-send", args = ["hello world"], env.WAYLAND_DISPLAY = "2" } }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Example 2:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[shortcuts]
|
||||||
|
ctrl-a = { type = "exec", exec = { shell = "grim - | wl-copy", privileged = true } }
|
||||||
|
```
|
||||||
fields:
|
fields:
|
||||||
prog:
|
prog:
|
||||||
kind: string
|
kind: string
|
||||||
required: true
|
required: false
|
||||||
description: The name of the executable.
|
description: The name of the executable.
|
||||||
|
shell:
|
||||||
|
kind: string
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
The name of a shell command to execute. The command will be executed as
|
||||||
|
`$SHELL -c "command"`.
|
||||||
args:
|
args:
|
||||||
kind: array
|
kind: array
|
||||||
required: false
|
required: false
|
||||||
items:
|
items:
|
||||||
kind: string
|
kind: string
|
||||||
description: The arguments to pass to the executable.
|
description: |
|
||||||
|
The arguments to pass to the executable.
|
||||||
|
|
||||||
|
This field must not be specified if a shell command is used.
|
||||||
env:
|
env:
|
||||||
kind: map
|
kind: map
|
||||||
required: false
|
required: false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue