You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Preliminary execution could add a judging step to shell command execution that would decide whether the actual action taking step can be executed or not.
For example, the following shell command opens up a currently focused file in GIMP image editor:
gimp {{file_path:absolute}}
However, there's no guard preventing executing the shell command if the currently open file is not an image. If e.g. a file named MyNote.md was open, gimp MyNote.md would launch GIMP, which would show an error message saying Opening 'MyNote.md' failed: Unknown file type.
If the shell command has a Preliminary execution setting toggled on (off by default), it can use a new variable {{execution_phase}} (the name can be improved) to check whether the shell command should perform its real action, or preliminary judging:
if [[ {{execution_phase}} = preliminary ]]
then# Preliminary phase.# Check if the file is an image.case {{file_extension:no-dot}} in
jpg|jpeg|png|bmp|gif) exit 0 ;; # GIMP can open this - show the command.*) exit 1 ;; # Not an image file - hide the command in Obsidian's command palette.esacelse# Real execution phase.
gimp {{file_path:absolute}}
fi
Preliminary phase is executed when...
... Obsidian's command palette is opened - so even before a shell command is selected for execution.
... other events, Shell commands URI, Execute now button in settings, or hotkeys are used to execute the shell command. In this case, the real execution phase will occur immediately after a successful preliminary phase.
Possible values for {{execution_phase}}
Phase
{{execution_phase}} value
Preliminary
preliminary
Real execution
Not decided yet. Ideas: main, real.
The variable allows developing more phases later, if any need arises (e.g. finishing phase or dry-run phase). Maybe there could be two preliminary phases: first one happening at command palette/menu opening, the second happening after user has chosen to execute a shell command, but before a prompt is opened up (if the shell command uses one). The second phase is good if a preliminary phase needs to perform some heavy task which should not be done every time command palette is opened.
Output from preliminary phase
Preliminary phase's output handling will differ vastly from the real phase:
For stdout, user selected output handlers will not be used. They are only meant to be used in the real execution phase.
For stderr, I haven't decided yet, but it might be possible that user selected output handlers could be used?
Output handling mode will always be Wait until finished, even if the real phase uses Realtime mode.
Output wrappers will not be used for stdout.
Ignore error codes will not be applied.
There could be two choices for a shell command to communicate its preliminary phase decision, either by an exit code, or by output to stdout.
Possible exit code values (maybe not in the first version?)
Exit codes offer a simple way to communicate whether the real phase can be executed or not without the verbosity of producing output text.
Exit code
0
Ok: the real phase can be executed.
1
Real phase cannot be executed. Show a disabled shell command in Obsidian's command palette and menus. (Command palette has no ability for showing a command as disabled, but if user tries to execute the shell command, and error message will be shown that the command is disabled.)
2
Real phase cannot be executed. Remove the shell command from Obsidian's command palette and menus.
Anything else
Behavior is not decided yet, and whatever it will be, it may change in later versions.
Output to stdout
For advanced features, the preliminary phase can output a JSON encoded object to stdout, containing the following properties.
Property
Possible values
Default value
executable
true: The shell command can be executed. Same as exit code 0. false: Cannot execute. Disable in command palette or menu. Same as exit code 1. null: Cannot execute. Remove from command palette or menu. Same as exit code 2.
Mandatory property, no default value.
shellCommandAlias (Consider changing to just alias?)
A string that will be used to override the shell command's alias text in command palette or menu. {{variables}} probably won't be supported (or will they?)
The shell command's default alias text.
menuChecked
true: Show a checked box in menus. Ignored in command palette. false: Show an empty box in menus. Ignored in command palette. null: Do not show a box.
null
menuIcon
A string icon name that will override the shell command's default icon in menus. Ignored in command palette. null: Do not show an icon.
The shell command's default icon.
customVariables
An object containing values that should be assigned to custom variables. Uses the same logic and features as output handler Assign custom variables. Allows the real execution phase to utilize data generated in the preliminary phase. Assignments can still be done even if further execution is denied.
{} (an empty object, i.e. no value assignments).
(An error message is shown and the real phase will not be executed, if mandatory properties are missing.)
Example output - file is not read-only, but can be made read-only:
If both an (over zero) exit code and output to stdout are detected
If output to stdout is not empty, it's considered that it should always be JSON. Any possible exit code is in this case ignored.
Possible later development: If output does not start with { or does not end with }, consider the output to be an alias text for the shell command.
If stderr output is detected along with stdout
To be decided.
Settings
Setting fields will be placed under the Preactions tab. (Consider renaming it to something else). Maybe allow enabling preliminary execution separately for the following things:
Command palette
Hotkeys (or do they need to be coupled together with command palette?)
Events
Shell commands URI
Execute now button in settings.
Prompts
If a shell command uses a prompt, the preliminary phase will be executed before the prompt is shown. If the preliminary phase denies further execution, no prompt will ever pop up.
This is handy for events that might execute shell commands rapidly: A preliminary phase can ensure user only gets prompted in circumstances where a shell command can really be run.
This brings error checking to happen before prompt opening instead of after it. At least for things that can be checked before getting input from user.
The preliminary phase can also output data to be shown on the prompt. For example, a shell command doing git commit -m {{_commit_message}} as its main action can use a prompt to ask for a commit message and also display the files that will be committed (i.e. git status which is executed by the preliminary phase and stored to a custom variable that will be shown in the prompt's description field).
There could also be a cancelled phase, which would be executed if the user decided to quit a prompt without executing the main phase. This could do some cleanup if needed.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Preliminary execution could add a judging step to shell command execution that would decide whether the actual action taking step can be executed or not.
For example, the following shell command opens up a currently focused file in GIMP image editor:
However, there's no guard preventing executing the shell command if the currently open file is not an image. If e.g. a file named
MyNote.md
was open,gimp MyNote.md
would launch GIMP, which would show an error message saying Opening 'MyNote.md' failed: Unknown file type.If the shell command has a Preliminary execution setting toggled on (off by default), it can use a new variable
{{execution_phase}}
(the name can be improved) to check whether the shell command should perform its real action, or preliminary judging:Preliminary phase is executed when...
Possible values for
{{execution_phase}}
{{execution_phase}}
valuepreliminary
main
,real
.The variable allows developing more phases later, if any need arises (e.g. finishing phase or dry-run phase). Maybe there could be two preliminary phases: first one happening at command palette/menu opening, the second happening after user has chosen to execute a shell command, but before a prompt is opened up (if the shell command uses one). The second phase is good if a preliminary phase needs to perform some heavy task which should not be done every time command palette is opened.
Output from preliminary phase
Preliminary phase's output handling will differ vastly from the real phase:
stdout
, user selected output handlers will not be used. They are only meant to be used in the real execution phase.stderr
, I haven't decided yet, but it might be possible that user selected output handlers could be used?stdout
.There could be two choices for a shell command to communicate its preliminary phase decision, either by an exit code, or by output to
stdout
.Possible exit code values (maybe not in the first version?)
Exit codes offer a simple way to communicate whether the real phase can be executed or not without the verbosity of producing output text.
0
1
2
Output to
stdout
For advanced features, the preliminary phase can output a JSON encoded object to
stdout
, containing the following properties.executable
true
: The shell command can be executed. Same as exit code0
.false
: Cannot execute. Disable in command palette or menu. Same as exit code1
.null
: Cannot execute. Remove from command palette or menu. Same as exit code2
.shellCommandAlias
(Consider changing to just
alias
?){{variables}}
probably won't be supported (or will they?)menuChecked
true
: Show a checked box in menus. Ignored in command palette.false
: Show an empty box in menus. Ignored in command palette.null
: Do not show a box.null
menuIcon
null
: Do not show an icon.customVariables
Allows the real execution phase to utilize data generated in the preliminary phase.
Assignments can still be done even if further execution is denied.
{}
(an empty object, i.e. no value assignments).(An error message is shown and the real phase will not be executed, if mandatory properties are missing.)
Example output - file is not read-only, but can be made read-only:
Example output - file is read-only, but can be made writable:
Example output - file is read-only and cannot be made writable this time:
Example output - with custom variable assignments:
If both an (over zero) exit code and output to
stdout
are detectedIf output to
stdout
is not empty, it's considered that it should always be JSON. Any possible exit code is in this case ignored.Possible later development: If output does not start with
{
or does not end with}
, consider the output to be an alias text for the shell command.If
stderr
output is detected along withstdout
To be decided.
Settings
Setting fields will be placed under the Preactions tab. (Consider renaming it to something else). Maybe allow enabling preliminary execution separately for the following things:
Prompts
If a shell command uses a prompt, the preliminary phase will be executed before the prompt is shown. If the preliminary phase denies further execution, no prompt will ever pop up.
git commit -m {{_commit_message}}
as its main action can use a prompt to ask for a commit message and also display the files that will be committed (i.e.git status
which is executed by the preliminary phase and stored to a custom variable that will be shown in the prompt's description field).cancelled
phase, which would be executed if the user decided to quit a prompt without executing the main phase. This could do some cleanup if needed.Beta Was this translation helpful? Give feedback.
All reactions