├── .gitignore ├── README.md ├── build-manual.sh ├── docs └── manual │ ├── images │ ├── buttons-sample.png │ ├── hello-checkbox-1.png │ ├── hello-dialog-2.png │ ├── hello-dialog-3.png │ ├── hello-dialog.png │ ├── hello-file-1.png │ ├── hello-world-in-catalog.png │ ├── new-script-prompt.png │ ├── refresh-catalog-button.png │ ├── run-hello-world.png │ ├── section-menu-exanded.png │ ├── section-menu.png │ ├── shellmarks-catalog-after-add-new.png │ ├── shellmarks-catalog-sample-scripts.png │ ├── shellmarks-catalog-samples.png │ └── shellmarks-catalog.png │ ├── index.adoc │ └── index.html ├── images ├── hello-world.png └── ipa-tools.png ├── img.png ├── index.js ├── package-lock.json ├── package.json ├── pom.xml ├── sample-scripts ├── buttons-sample.sh ├── hello.php ├── hello.sh ├── ipa-util.sh ├── pytube.sh ├── server-management-sample.sh └── test-script.sh └── src └── main ├── java ├── META-INF │ └── MANIFEST.MF └── ca │ └── weblite │ └── shellmarks │ ├── DocumentationAppFX.java │ ├── Main.java │ └── RunScriptListener.java └── resources └── ca └── weblite └── shellmarks ├── documentation.js └── welcome.adoc /.gitignore: -------------------------------------------------------------------------------- 1 | jdeploy-bundle 2 | out 3 | target 4 | node_modules 5 | .idea 6 | build 7 | *.iml 8 | jdeploy 9 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shellmarks 2 | A documentation and GUI generator for your custom shell scripts. 3 | 4 | ## Synopsis 5 | 6 | Shellmarks is a productivity tool for developers who create lots of custom shell scripts, but can't remember where they saved them, how to use them, or both. It provides: 7 | 8 | 1. *A GUI markup language* (using [TOML](https://toml.io/en/)) that can be embedded directly into a shell script. When the script is run using shellmarks, it will display a dialog to the user, prompting them to provide some environment variables. Currently the dialog can contain text fields, file selection fields, buttons, and checkbox fields, but more field types can easily be added as needs be. 9 | 2. *A searchable catalog of all of your installed scripts*. The catalog includes documentation for each script, as well as buttons to _Run_, _Edit_, _Clone_, and _Delete_ them. 10 | 11 | [Watch Screencast Intro (12 minutes)](https://youtu.be/8JwSA3rh39Y) 12 | 13 | ## License 14 | 15 | MIT 16 | 17 | ## Features 18 | 19 | - *GUI Dialog Generation* - Shellmarks makes it easy to add a GUI dialog to a shell script to allow users to enter environment variables and run the script. 20 | - *Shell Script Catalog* - Shellmarks generates a script catalog of all of your custom scripts, along with documentation and UI options to run and edit your scripts. 21 | - *Compatible with Default Shell Interpreters* - Scripts with Shellmarks markup remain fully compatible with the built-in shell script interpreter. If you run the script directly in, for example, _bash_, it will just run the script normally. If you run it with _shellmarks_, it will first display a GUI dialog to let the user set up the script's environment, and then run the script in the default interpreter. 22 | - *Multi-language Support* - You can write your shell scripts in any language you like. Shellmarks just uses the "hashbang" to know which interpreter to send the script to. 23 | 24 | ## Hello World 25 | 26 | The following is a simple script that prints _hello ${name}_, where _${name}_ is provided by the user. 27 | 28 | ```bash 29 | #!/bin/bash 30 | echo "Hello ${name}" 31 | exit 0 32 | --- 33 | [name] 34 | type="text" 35 | label="Please enter your name" 36 | required=true 37 | ``` 38 | 39 | If you run this script using _bash_ directly, it will simply output: 40 | 41 | ~~~ 42 | Hello 43 | ~~~ 44 | 45 | This is because the _${name}_ environment variable is not set. 46 | 47 | If you, instead, run this with `shellmarks`, it will prompt the user to enter their name in a GUI dialog: 48 | 49 | ![Hello World](images/hello-world.png) 50 | 51 | If the user enters "Steve" into the text field, and presses "Run", they'll see the following output in the console. 52 | 53 | ~~~ 54 | Hello Steve 55 | ~~~ 56 | 57 | ## More Advanced Example 58 | 59 | The following script is a more advanced example that involves a few more field types. The script is one that I wrote to extract the entitlements and provisioning profile information from an IPA file. I use this script quite frequently to help support users of [Codename One](https://www.codenameone.com) when they run into issues relating to entitlements and certificates on their iOS apps. 60 | 61 | ```bash 62 | #!/bin/bash 63 | file_extracted="${file}-extracted" 64 | if [ ! -d "${file_extracted}" ]; then 65 | if [ ! -f "$file" ]; then 66 | echo "Cannot find file $file" 67 | exit 1 68 | fi 69 | mkdir "${file_extracted}" 70 | cp "$file" "${file_extracted}/App.zip" 71 | cd "${file_extracted}" 72 | unzip App.zip 73 | else 74 | cd ${file_extracted} 75 | fi 76 | appname=$(ls Payload | grep '\.app$') 77 | if [ ! -z "$showEntitlements" ]; then 78 | codesign -d --entitlements :- "Payload/${appname}" 79 | fi 80 | if [ ! -z "$showProvisioningProfile" ]; then 81 | security cms -D -i "Payload/${appname}/embedded.mobileprovision" 82 | fi 83 | exit 0 84 | --- 85 | __title__="IPA Entitlements" 86 | __description__=''' 87 | This script will print out the entitlements and provisioning profile for given .ipa file. 88 | 89 | See https://developer.apple.com/library/archive/qa/qa1798/_index.html[Apple Tech Article] for more information. 90 | ''' 91 | [file] 92 | type="file" 93 | label="Select ipa file" 94 | required=true 95 | help="Select the .ipa file that you wish to inspect." 96 | 97 | [showEntitlements] 98 | type="checkbox" 99 | label="Show Entitlements" 100 | default="true" 101 | help="Check this to show the ipa entitlements." 102 | 103 | [showProvisioningProfile] 104 | type="checkbox" 105 | label="Show Provisioning Profile" 106 | default="true" 107 | help="Check this to show the ipa provisioning profile details." 108 | ``` 109 | 110 | If this script is in a file named _ipa-tools.sh_, then you can run it via: 111 | 112 | ~~~ 113 | shellmarks ipa-tools.sh 114 | ~~~ 115 | 116 | The GUI dialog looks like: 117 | 118 | ![ipa-tools](images/ipa-tools.png) 119 | 120 | ## Script Structure 121 | 122 | Shell scripts written for _shellmarks_ are just regular shell scripts. At the end of the script you simply add a section with: 123 | 124 | ~~~ 125 | exit 0 126 | --- 127 | ... Your GUI definitions here in TOML format 128 | ~~~ 129 | 130 | Some notes: 131 | 132 | We add `exit 0` so that the script exits before reaching the shellmarks GUI configuration. This ensures that the script will remain compatible with the default shell iterpreter (e.g. bash). 133 | 134 | The `---` serves as a dividing line between the script content, and the shellmarks config. 135 | 136 | The contents of this tag will be interpreted as [TOML](https://toml.io/en/). 137 | 138 | ## Script Catalog 139 | 140 | If you run `shellmarks` with no arguments, it will open up the script catalog with all of the scripts that you've installed into shellmarks. 141 | 142 | Each installed script in the catalog is rendered with an entry that allows you to run, edit, delete, or clone it. 143 | 144 | ![Script Catalog](https://shannah.github.io/shellmarks/manual/images/shellmarks-catalog-samples.png) 145 | 146 | ## Installation 147 | 148 | Installation requires that you have NodeJS installed, because the installer uses npm. 149 | 150 | [Download NodeJS here](https://nodejs.org/en/download/) 151 | 152 | Then, open a terminal, and enter: 153 | 154 | ```bash 155 | sudo npm install -g shellmarks 156 | ``` 157 | 158 | NOTE: On windows you may not require the "sudo" part. Just `npm install -g shellmarks` 159 | 160 | On Mac and Linux the `sudo` is required to give npm access to install it globally. 161 | 162 | ## Requirements 163 | 164 | Shellmarks should run on any modern Windows, Linux, or Mac system. 165 | 166 | ## Documentation 167 | 168 | - [Users Manual](https://shannah.github.io/shellmarks/manual) 169 | - [CLI Usage](https://shannah.github.io/shellmarks/manual/#cli) 170 | - [GUI Form Configuration](https://shannah.github.io/shellmarks/manual/#config) 171 | - [Sample Scripts](sample-scripts) 172 | - [Screencast Intro Video](https://youtu.be/8JwSA3rh39Y) 173 | 174 | ## Credits 175 | 176 | Shellmarks was created by [Steve Hannah](https://sjhannah.com). It owes a great deal to the Java open source eco-system, as its development would have been much more difficult without the mature set of Maven dependencies. 177 | 178 | Notable dependencies: 179 | 180 | - *[AsciiDoctor](https://asciidoctor.org/)* - Shellmarks uses AsciiDoctor to generate the HTML used for the script catalog. 181 | - *[JavaFX](https://openjfx.io/)* - The Script catalog interface is written in JavaFX, a top quality cross-platform UI library. 182 | - *[TOML](https://toml.io/en/)* - Shellmarks needed a simple and concise syntax for describing its UI forms, and TOML fit the bill perfectly. Less verbose than XML and JSON, and easier to work with than yml. API was simple to use. Just dropped in a maven dependency, and I was off and running. 183 | 184 | See the [pom.xml file](pom.xml) for a full list of dependencies. 185 | 186 | jDeploy app signature: a68277ce4f5b15f1f374053a9ca5188d440e84fe725d2a3fcda45026c87f4127 187 | -------------------------------------------------------------------------------- /build-manual.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd docs/manual 3 | asciidoctor index.adoc -------------------------------------------------------------------------------- /docs/manual/images/buttons-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/buttons-sample.png -------------------------------------------------------------------------------- /docs/manual/images/hello-checkbox-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-checkbox-1.png -------------------------------------------------------------------------------- /docs/manual/images/hello-dialog-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-dialog-2.png -------------------------------------------------------------------------------- /docs/manual/images/hello-dialog-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-dialog-3.png -------------------------------------------------------------------------------- /docs/manual/images/hello-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-dialog.png -------------------------------------------------------------------------------- /docs/manual/images/hello-file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-file-1.png -------------------------------------------------------------------------------- /docs/manual/images/hello-world-in-catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/hello-world-in-catalog.png -------------------------------------------------------------------------------- /docs/manual/images/new-script-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/new-script-prompt.png -------------------------------------------------------------------------------- /docs/manual/images/refresh-catalog-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/refresh-catalog-button.png -------------------------------------------------------------------------------- /docs/manual/images/run-hello-world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/run-hello-world.png -------------------------------------------------------------------------------- /docs/manual/images/section-menu-exanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/section-menu-exanded.png -------------------------------------------------------------------------------- /docs/manual/images/section-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/section-menu.png -------------------------------------------------------------------------------- /docs/manual/images/shellmarks-catalog-after-add-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/shellmarks-catalog-after-add-new.png -------------------------------------------------------------------------------- /docs/manual/images/shellmarks-catalog-sample-scripts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/shellmarks-catalog-sample-scripts.png -------------------------------------------------------------------------------- /docs/manual/images/shellmarks-catalog-samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/shellmarks-catalog-samples.png -------------------------------------------------------------------------------- /docs/manual/images/shellmarks-catalog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shannah/shellmarks/0d36a0d10e48a6a7595c05ed52ec506e46fc6bda/docs/manual/images/shellmarks-catalog.png -------------------------------------------------------------------------------- /docs/manual/index.adoc: -------------------------------------------------------------------------------- 1 | = Shellmarks User Guide 2 | Steve Hannah 3 | v1.0.0, 2021-12-20 4 | :description: This document contains usage instructions for the Shellmarks application. 5 | :doctype: book 6 | :toc: 7 | :sectnums: 8 | :icons: font 9 | 10 | > A documentation and GUI generator for your custom shell scripts. 11 | 12 | [introduction] 13 | = Introduction 14 | 15 | [discrete] 16 | == The Problem 17 | 18 | Over the years, as a software developer, I've amassed a shed-load of shell scripts for automating various frequently-used (or _potentially_ frequently-used) tasks. While these scripts have undeniably helped my productivity, their full utility remains unrealized due to two thorny impediments: 19 | 20 | 1. *I forget where I _put_ the scripts*. Sometimes I create a script to help with a particular project, so I save it in a location that is associated with that project. Later on, I face a similar problem on a different project, and I recall that I wrote a script that may apply here, but I don't remember exactly where I saved the script, or what it was called. I may not even remember which computer I saved it on. What is the MacBook, or the iMac. I don't recall. So I'll just write the same thing again from scratch. 21 | 2. *I forget how to _use_ the scripts.* What flags do I need to set? Does the script expect any environment variables to be set? Before using an old script, I need to read through the full script again to _download_ it into my brain and determine its applicability to the current situation. 22 | 23 | [discrete] 24 | == The Vision 25 | Every once in a while I think, wouldn't it be nice to have a single, well-structured webpage that included documentation for all of the tasks that I may need to perform on a daily basis? Something like a personal _O'Reilly_ book with chapters for all of the projects, clients, and topics that relate to my work. 26 | 27 | Further, wouldn't it be nice if my shell scripts included a graphical user interface for setting the required flags and environment variables? If, for example, the script is designed to perform some task on a particular directory or file, the GUI would include a file dialog for selecting this file. 28 | 29 | [discrete] 30 | == The Solution: Shellmarks 31 | 32 | Shellmarks is the embodiment of this vision. It includes two parts: 33 | 34 | 1. *A GUI markup language* (using https://toml.io/en/[TOML syntax]) that can be embedded directly into a shell script. When the script is run using shellmarks, it will display a dialog to the user, prompting them to provide some environment variables. Currently the dialog can contain text fields, file selection fields, buttons, and checkbox fields, but more field types can easily be added as needs be. 35 | 2. *A searchable catalog of all of your installed scripts*. The catalog includes documentation for each script, as well as buttons to _Run_, _Edit_, _Clone_, and _Delete_ them. 36 | 37 | [getting-started] 38 | = Getting Started 39 | 40 | == Installation 41 | 42 | NOTE: We use https://www.npmjs.com/[npm] for installation because it is cross-platform and easy to use. _npm_ comes with NodeJS, which can be downloaded from https://nodejs.org/en/download/[here]. 43 | 44 | [source,bash] 45 | ---- 46 | sudo npm install -g shellmarks 47 | ---- 48 | 49 | TIP: _sudo_ is required here on Mac and Linux, because we want to install it globally. That is what the `-g` flag is for. `sudo` is not required on Windows. 50 | 51 | == Your First Script 52 | 53 | For our first script, let's write a simple "Hello World" script: 54 | 55 | [source,bash] 56 | ---- 57 | #!/bin/bash <1> 58 | echo "Hello ${name}" <2> 59 | exit 0 <3> 60 | ---<4> 61 | [name] <5> 62 | ---- 63 | <1> Hash-bang is required so that shellmarks knows which shell interpreter to run the script through after it displays the UI dialog. 64 | <2> We echo `"Hello ${name}"` where `${name}` is an environment variable that we supply in the UI dialog. 65 | <3> We need to explicitly exit the script before the Shellmarks UI markup begins. 66 | <4> The `---` divider, on a line of its own, tell _shellmarks_ where the UI markup begins. Everything after this line will be interpreted as the UI markup, and must be valid https://toml.io/en/[TOML]. 67 | <5> We declare a "name" field in the UI dialog for setting the `${name}` environment variable. 68 | 69 | Save this script in a file named "hello.sh", then run it from the command-line with: 70 | 71 | [source,bash] 72 | ---- 73 | shellmarks hello.sh 74 | ---- 75 | 76 | This will prompt you with the following dialog: 77 | 78 | image::images/hello-dialog.png[] 79 | 80 | Enter "Duke" into the _name_ text field, and press "Run". You should then see the following in the console: 81 | 82 | [source,listing] 83 | ---- 84 | Hello Duke 85 | ---- 86 | 87 | === Customizing the Name Field 88 | 89 | The above example is a bare minimal example that displays a single text field. You can customize the field label using the _label_ property. You can also make the field required using the _required_ property. And you can set a default value using the _default_ property. For example: 90 | 91 | [source,bash] 92 | ---- 93 | #!/bin/bash 94 | echo "Hello ${name}" 95 | exit 0 96 | --- 97 | [name] 98 | label="Enter your name" 99 | help="This will be displayed in a tooltip" 100 | required=true 101 | default="Jimbo" 102 | ---- 103 | 104 | image::images/hello-dialog-2.png[] 105 | 106 | === Customizing Dialog Title and Help Text 107 | 108 | You can customize the the dialog title using the _\__title___ property. You can also provide some text to be displayed at the top of the form using the _\__description___ property, as follows: 109 | 110 | [source,bash] 111 | ---- 112 | #!/bin/bash 113 | echo "Hello ${name}" 114 | exit 0 115 | --- 116 | __title__="Hello World" 117 | __description__=''' 118 | This example shows you how to add some help text to the top of the dialog. 119 | 120 | This content is in Asciidoc format, and supports markup such as https://www.example.com[links]. 121 | ''' 122 | 123 | [name] 124 | label="Enter your name" 125 | help="This will be displayed in a tooltip" 126 | required=true 127 | default="Jimbo" 128 | ---- 129 | 130 | image::images/hello-dialog-3.png[] 131 | 132 | === File Selection 133 | 134 | It is quite common to take a file or directory as input in a shell script. For example, let's add some output in our script that displays the word count for a file. We can use the `type="file"` in the field description to allow the user to select a file or directory. 135 | 136 | [source,bash] 137 | ---- 138 | #!/bin/bash 139 | echo "Hello ${name}" 140 | wordcount=$(wc "${file}") 141 | echo "Word count in ${file} is ${wordcount}" 142 | exit 0 143 | --- 144 | __title__="Hello World" 145 | __description__=''' 146 | This example shows you how to add some help text to the top of the dialog. 147 | 148 | This content is in Asciidoc format, and supports markup such as https://www.example.com[links]. 149 | ''' 150 | 151 | [name] 152 | label="Enter your name" 153 | help="This will be displayed in a tooltip" 154 | required=true 155 | default="Jimbo" 156 | 157 | [file] 158 | type="file" 159 | label="Please select a file" 160 | help="The word count for the selected file will be output" 161 | required=true 162 | ---- 163 | 164 | image::images/hello-file-1.png[] 165 | 166 | Notice here that the _file_ field includes a text field and a "..." button. In the text field you could simply type or paste teh path to a file. Pressing the "..." button will show a file dialog where you can select a file. 167 | 168 | === Checkboxes 169 | 170 | In some cases, you may want the user to select between two different options: "on" or "off". You can use the _checkbox_ field type to handle this. For example, Let's make the _wordcount_ feature of our script optional, so that it is only shown when the user checks the "Show wordcount" option. 171 | 172 | E.g. 173 | 174 | [source,bash] 175 | ---- 176 | #!/bin/bash 177 | echo "Hello ${name}" 178 | if [ ! -z "$showWordcount" ]; then <1> 179 | wordcount=$(wc "${file}") 180 | echo "Word count in ${file} is ${wordcount}" 181 | fi 182 | exit 0 183 | --- 184 | __title__="Hello World" 185 | __description__=''' 186 | This example shows you how to add some help text to the top of the dialog. 187 | 188 | This content is in Asciidoc format, and supports markup such as https://www.example.com[links]. 189 | ''' 190 | 191 | [name] 192 | label="Enter your name" 193 | help="This will be displayed in a tooltip" 194 | required=true 195 | default="Jimbo" 196 | 197 | [showWordcount] 198 | label="Show wordcount" 199 | help="Check this box to display the wordcount of a file." 200 | type="checkbox" <2> 201 | 202 | [file] 203 | type="file" 204 | label="Please select a file" 205 | help="The word count for the selected file will be output" 206 | ---- 207 | <1> We use `if [ ! -z "$showWordcount" ]` to check if the `$showWordcount` environment variable is not empty, and only do the _wordcount_ stuff in that case. 208 | <2> We set `type="checkbox"` for the `showWordcount` field so that it is rendered with a checkbox. 209 | 210 | image::images/hello-checkbox-1.png[] 211 | 212 | === Buttons 213 | 214 | The "button" type provides an alternate way to pass boolean values to your script. If you define any fields with the "button" type, they will be rendered on your script's dialog instead of the standard "Run" button. Pressing the button will run the script, but with the corresponding environment variable set to "1". 215 | 216 | .Example: A dialog with 3 buttons. 217 | [source,bash] 218 | ---- 219 | #!/bin/bash 220 | 221 | if [ ! -z "$button1Clicked" ]; then 222 | echo "Button 1 was clicked" 223 | fi 224 | if [ ! -z "$button2Clicked" ]; then 225 | echo "Button 2 was clicked" 226 | fi 227 | if [ ! -z "$button3Clicked" ]; then 228 | echo "Button 3 was clicked" 229 | fi 230 | exit 0 231 | --- 232 | # The script title 233 | __title__="Buttons Sample" 234 | 235 | # Script description in Asciidoc format 236 | __description__=''' 237 | This example shows how to use the 'button' field type to add multiple submit buttons on your dialog. 238 | ''' 239 | 240 | # Tags used to place script into one or more sections of the catalog 241 | __tags__="#samples" 242 | 243 | [button1Clicked] 244 | label="Button 1" 245 | type="button" 246 | 247 | [button2Clicked] 248 | label="Button 2" 249 | type="button" 250 | 251 | [button3Clicked] 252 | label="Button 3" 253 | type="button" 254 | 255 | ---- 256 | 257 | The dialog for this script is: 258 | 259 | image::images/buttons-sample.png[] 260 | 261 | If you click on "Button 1", it will set the `${button1Clicked}` environment variable, so the script can detect this case. Similarly the other buttons will set their corresponding environment variable when they are pressed. 262 | 263 | ==== Dispose On Submit 264 | 265 | The default behaviour of shellmarks is to dispose the dialog when the user submits the form by either pressing the "Run" button or a button defined by a field with `type="button"`. In some cases, you may want to keep the dialog open so that you can run the script again with different settings. For example a server management script might include buttons to _Start_, _Stop_, and _Check Status_ on the server. In this case you may want to run _Check Status_ first to see if the server is running, and then press _Start_ to start the server. It would be annoying if the dialog closed after checking the status. 266 | 267 | You can use the _disposeOnSubmit_ property to control this: 268 | 269 | e.g. 270 | 271 | [source,bash] 272 | ---- 273 | [startServer] 274 | type="button" 275 | label="Start Server" 276 | disposeOnSubmit=false 277 | 278 | [stopServer] 279 | type="button" 280 | label="Stop Server" 281 | disposeOnSubmit=false 282 | 283 | [serverStatus] 284 | type="button" 285 | label="Check Server Status" 286 | disposeOnSubmit=false 287 | ---- 288 | 289 | 290 | == The Shellmarks Catalog 291 | 292 | We've already seen how shellmarks can provide a GUI for individual shell scripts. It gets better, though. If you run `shellmarks` without any arguments, it will open a catalog of all of your installed scripts, including documentation, and the ability to run your scripts by pressing a "Run" button. 293 | 294 | .Open the Shellmarks catalog by simply running _shellmarks_ with no arguments. 295 | [source,bash] 296 | ---- 297 | shellmarks 298 | ---- 299 | 300 | image::images/shellmarks-catalog.png[] 301 | 302 | The first time you open the catalog, it won't have any scripts listed. You can add scripts to your catalog by either creating a new script, or by importing an existing one. To create a new script, click the "Create New Script" link in the main menu. To import an existing script, you can press "From File", or "From URL" depending on whether you are loading it from a local file or from a network URL. 303 | 304 | Let's start by creating a new script. Click "Create New Script". 305 | 306 | You'll be prompted to enter a name for the script: 307 | 308 | image::images/new-script-prompt.png[] 309 | 310 | Enter "hello-world.sh" for the name, and press "OK". 311 | 312 | If all goes well, it should open the script for editing in your default text editor. To help you get started, the script will be pre-populated with a default shell script. This template may change over time, but at the time of writing, the default script contents are: 313 | 314 | [source,bash] 315 | ---- 316 | #!/bin/bash 317 | echo "Hello ${firstName} ${lastName}" 318 | echo "You selected ${selectedFile}" 319 | if [ ! -z "${option1}" ]; then 320 | echo "Option1 was selected" 321 | fi 322 | if [ ! -z "${option2}" ]; then 323 | echo "Option2 was selected" 324 | fi 325 | exit 0 326 | --- 327 | # The script title 328 | __title__="hello-world.sh" 329 | 330 | # Script description in Asciidoc format 331 | __description__=''' 332 | This description will be displayed at the top of the form. 333 | 334 | It can be multiline and include https://example.com[Links] 335 | ''' 336 | 337 | # Doc string. In asciidoc format. Displayed in Shellmarks catalog 338 | __doc__=''' 339 | This will be displayed in the shellmarks catalog. 340 | 341 | You can include _asciidoc_ markup, as well as https://www.example.com[links]. 342 | ''' 343 | 344 | # Tags used to place script into one or more sections of the catalog 345 | __tags__="#custom-tag1 #custom-tag2" 346 | 347 | [firstName] 348 | label="First Name" 349 | required=true 350 | 351 | [lastName] 352 | label="Last Name" 353 | 354 | [selectedFile] 355 | label="Please select a file" 356 | type="file" 357 | 358 | [option1] 359 | label="Option 1" 360 | type="checkbox" 361 | 362 | [option2] 363 | label="Option 2" 364 | type="checkbox" 365 | 366 | ---- 367 | 368 | 369 | It is just a simple script that prompts the user for their first and last name, and it prints "Hello FIRSTNAME LASTNAME" to the console. If you go back into the Shellmarks catalog, you should see your script listed now. 370 | 371 | 372 | image::images/shellmarks-catalog-after-add-new.png[] 373 | 374 | In the _Table of Contents_, you should see two instances of the _hello-world.sh_ script you just created. One under "custom Tag 1", and the other under "custom Tag2". This is because the script includes a `__tags__` property with two tags: "#custom-tag1 #custom-tag2". Tags allow you to categorize your scripts into sections. We'll discuss those in more depth later. 375 | 376 | Either scroll down to the "hello-world.sh" script, or click one of the links to it in the table of contents. You should see an entry as follows: 377 | 378 | image::images/hello-world-in-catalog.png[] 379 | 380 | All of this information is pulled directly from the properties in the _hello-world.sh_. Script. It includes a description that is taken from the `\\__doc__` property. It shows the script _command_ which can be pasted into the terminal to run the script directly. And it provides four buttons: 381 | 382 | Run:: 383 | Runs the script directly. 384 | Edit:: 385 | Opens the script to be edited in the system text editor. 386 | Delete:: 387 | Delete's the script 388 | Clone:: 389 | Makes a clone of the script. 390 | 391 | Press "Run" to run the script. It should open the script's dialog as shown here: 392 | 393 | image::images/run-hello-world.png[] 394 | 395 | If you enter data into the form fields and press "Run", you'll see the script output in the console. 396 | 397 | TIP: The script output will appear in the terminal window that you used to launch shellmarks originally. 398 | 399 | === Creating a "Samples" category 400 | 401 | Currently, our script is filed under two categories "custom Tag1", and "custom Tag2". Let's move it to a new category called "Samples". 402 | 403 | Press the "Edit" button under the "hello-world.sh" script to open the script for editing. Then changes the `\\__tags__` property to the following: 404 | 405 | [source,bash] 406 | ---- 407 | __tags__="#samples" 408 | ---- 409 | 410 | Save these changes and return to the Shellmarks catalog and press the "Refresh" button in the upper left: 411 | 412 | image::images/refresh-catalog-button.png[] 413 | 414 | You should notice that the table of contents is changed. Instead of "custom Tag1", and "custom Tag2", it has a "samples" option: 415 | 416 | 417 | image::images/shellmarks-catalog-samples.png[] 418 | 419 | Now, let's customize the label for the "Samples" section add a description. Notice to the right of the "samples" heading, there is a menu button. 420 | 421 | image::images/section-menu.png[] 422 | 423 | Press this button to expand the menu: 424 | 425 | image::images/section-menu-exanded.png[] 426 | 427 | Now press the "Edit Section" menu item. 428 | 429 | This will create an Asciidoc file with the section details in the system text editor. If this is the first time you are editing the section, it will generate some default content: 430 | 431 | [source,asciidoc] 432 | ---- 433 | = samples 434 | 435 | This is the section description formatted as https://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoc] 436 | 437 | Lorem ipsum, etc... 438 | ---- 439 | 440 | The first line will be used as the title of the section, and all of the content below it will be displayed in the catalog at the beginning of the section. Let's change this to the following: 441 | 442 | [source,asciidoc] 443 | ---- 444 | = Sample Scripts 445 | 446 | This section includes a few sample scripts to demonstrate Shellmarks' syntax. 447 | ---- 448 | 449 | Save the changes and reload the Shellmarks catalog, and you should see the following: 450 | 451 | image::images/shellmarks-catalog-sample-scripts.png[] 452 | 453 | Notice that the section title is now "Sample Scripts", rather than "samples". This is because we changed the heading in the section file. Additionally, the section now includes a helpful description that was taken directly from our input. 454 | 455 | TIP: You can include as much or as little content as you like in your section files. You can even create sub-headings. All headings will be rendered with the appropriate heading level in the shellmarks catalog. 456 | 457 | [faq] 458 | = Frequently Asked Questions 459 | 460 | == Script Syntax 461 | 462 | === What format is used for the Shellmark script GUI metadata? 463 | 464 | Shellmark uses https://toml.io/en/[TOML] for all GUI metadata. 465 | 466 | === What scripting languages are supported by shellmarks? 467 | 468 | You can use any scripting language you like for your shell scripts. You just need to have the language installed on your computer, and the "hash-bang" line of your shell script should point to the interpreter. E.g. If the script begins with: `#!/bin/bash`, it will use the bash shell interpreter. 469 | 470 | For example, consider the following is the PHP equivalent of the default "Hello" script: 471 | 472 | [source,php] 473 | ---- 474 | #!/usr/bin/php 475 | 492 | --- 493 | # The script title 494 | __title__="hello-php.php" 495 | 496 | # Script description in Asciidoc format 497 | __description__=''' 498 | This description will be displayed at the top of the form. 499 | 500 | It can be multiline and include https://example.com[Links] 501 | ''' 502 | 503 | # Doc string. In asciidoc format. Displayed in Shellmarks catalog 504 | __doc__=''' 505 | This will be displayed in the shellmarks catalog. 506 | 507 | You can include _asciidoc_ markup, as well as https://www.example.com[links]. 508 | ''' 509 | 510 | # Tags used to place script into one or more sections of the catalog 511 | __tags__="#custom-tag1 #custom-tag2" 512 | 513 | [firstName] 514 | label="First Name" 515 | required=true 516 | 517 | [lastName] 518 | label="Last Name" 519 | 520 | [selectedFile] 521 | label="Please select a file" 522 | type="file" 523 | 524 | [option1] 525 | label="Option 1" 526 | type="checkbox" 527 | 528 | [option2] 529 | label="Option 2" 530 | type="checkbox" 531 | 532 | ---- 533 | 534 | == Shellmarks Catalog 535 | 536 | === Where are the scripts in the catalog stored? 537 | 538 | Shellmarks stores all scripts in the `$HOME/.shellmarks/scripts` directory, where `$HOME` refers to the user's home directory. 539 | 540 | This location can be overridden via the `SHELLMARKS_PATH` environment variable, whose default value is `$HOME/.shellmarks/scripts`. 541 | 542 | === Can I run multiple shellmarks instances with different catalogs? 543 | 544 | Yes, by launching different instances of shellmarks with different values for the `SHELLMARKS_PATH` environment variable. 545 | 546 | E.g. 547 | 548 | [source, bash] 549 | ---- 550 | shellmarks #launch with default catalog 551 | 552 | SHELLMARKS_PATH=/tmp/temp_catalog shellmarks #launch with scripts in /tmp/temp_catalog 553 | ---- 554 | 555 | === Can I organize my scripts into categories? 556 | 557 | Yes. You can use the `\\__tags__` property in your script. For example, the following script will be filed in the "samples" section of the catalog. 558 | 559 | [source,bash] 560 | ---- 561 | #!/bin/bash 562 | echo "Hello" 563 | exit 0 564 | -- 565 | __tags__="#samples" 566 | ---- 567 | 568 | TIP: You can add your script to multiple categories by adding multiple tags. E.g. `\\__tags__="#category1 #category2"` 569 | 570 | === Can I Organize my Categories into a heirarchy with Sub-Categories? 571 | 572 | Yes. You can use the `:parent:` directive in the section content, just underneath the section header. Suppose we have two categories "ios" and "android" that we want group under the umbrella category "mobiledev". 573 | 574 | Then we can edit the "ios" section and change the content to: 575 | 576 | [source,asciidoc] 577 | ---- 578 | # iOS Development 579 | :parent: mobiledev 580 | 581 | Scripts related to iOS development 582 | ---- 583 | 584 | And edit the "android" section, changing the content to: 585 | 586 | [source,asciidoc] 587 | ---- 588 | # Android Development 589 | :parent: mobiledev 590 | 591 | Scripts related to Android development. 592 | ---- 593 | 594 | This is sufficient to have "ios" and "android" grouped under "mobiledev". We could further customize the label and description for the "mobiledev" parent category by editing the section with the following: 595 | 596 | [source,asciidoc] 597 | ---- 598 | # Mobile Development 599 | 600 | This section contains content for mobile development 601 | ---- 602 | 603 | === Can I add custom content to the catalog, unrelated to scripts? 604 | 605 | Yes. You can add sections using the "New Section" option. You can then proceed to add arbitrary content in Asciidoc format. 606 | 607 | === Can I trigger a script to run via a link? 608 | 609 | Yes. You can trigger actions to run from _section_ content (Asciidoc) using a link of the form "https://runScript/SCRIPTNAME" where SCRIPTNAME is the name of your script. 610 | 611 | .Adding a link that runs the _hello.sh_ script directly: 612 | [source,asciidoc] 613 | ---- 614 | https://runScript/hello.sh[Run hello.sh script] 615 | ---- 616 | 617 | You can even set default environment variables for the script by adding a query string. E.g.: 618 | 619 | [source,asciidoc] 620 | ---- 621 | https://runScript/hello.sh?firstName=Steve&lastName=Hannah[Run hello.sh script] 622 | ---- 623 | 624 | When you click on this link in the catalog, it will run the `hello.sh` script but with the _firstName_ and _lastName_ environment variables set to "Steve" and "Hannah" respectively. 625 | 626 | [reference] 627 | = Reference 628 | 629 | == Shellmarks Script Syntax 630 | 631 | Shellmarks scripts use the following structure: 632 | 633 | [source,bash] 634 | ---- 635 | #!/bin/bash <1> 636 | 637 | # ... Shell script source ... 638 | 639 | exit 0 <2> 640 | --- <3> 641 | 642 | # ... Shellmarks Configuration here ... 643 | 644 | ---- 645 | <1> "Hash-bang" line tells the script which shell interpreter to use. E.g. `#!/bin/bash`, `#!/usr/bin/php`, etc.... Any installed interpreter should work. 646 | <2> An _exit_ statement marks the end of the shell script so that the interpreter (e.g _bash_) doesn't try to execute the shellmarks configuration that follows. 647 | <3> A dividing line marking the beginning of the Shellmarks configuration. 648 | 649 | [#config] 650 | === Shellmarks Configuration 651 | 652 | Shellmark configuration should be valid TOML. Script properties typically pertain to the the script as a whole. Field properties apply to individual fields, and are only valid when used inside a field's configuration section. 653 | 654 | ==== Script Properties 655 | 656 | \\__title__:: 657 | The title of the script. This will be displayed in the Shellmarks catalog, and also as the dialog title when the script is run. 658 | + 659 | .Example 660 | [source,toml] 661 | ---- 662 | __title__="My Cool Script" 663 | ---- 664 | \\__description__:: 665 | A description of how to use the script, or what it does. This is displayed at the top of the dialog that is displayed when the script is run. It may be a multi-line string, and should be in Asciidoc format. If the `\\__doc___` property is not defined, then this will also be displayed in the Shellmarks catalog for the script's details. 666 | + 667 | .Example 668 | [source,toml] 669 | ---- 670 | __description__=''' 671 | This script does a bunch of cool things. 672 | 673 | See https://www.example.com[my website] for more usage instructions. 674 | ''' 675 | ---- 676 | \\__doc__:: 677 | Documentation for the script that will be displayed for the script in the Shellmarks catalog. If this is not defined, then the `\\__description__` property will be used instead. This may be a multi-line string, and should be in Asciidoc format. 678 | + 679 | .Example 680 | [source,toml] 681 | ---- 682 | __doc__=''' 683 | This script does a bunch of cool things. 684 | 685 | See https://www.example.com[my website] for more usage instructions. 686 | ''' 687 | ---- 688 | \\__tags__:: 689 | One or more "tags" that can be used to mark which categories the script is listed in in the catalog. Each tag should be prefixed with `#`. 690 | + 691 | .Example 692 | [source,toml] 693 | ---- 694 | __tags__="#iosdev #macdev" 695 | ---- 696 | 697 | ==== Field Properties 698 | 699 | label:: 700 | The field label. If this isn't defined it will just use the field name as its label. 701 | + 702 | .Example 703 | [source,toml] 704 | ---- 705 | label="First Name" 706 | ---- 707 | 708 | help:: 709 | Tooltip text to display when the user hovers the pointer over the field. Optional. 710 | + 711 | .Example 712 | [source,toml] 713 | ---- 714 | help="This is some tooltip text" 715 | ---- 716 | 717 | default:: 718 | A default value to use for this field. When the dialog is shown, it will prefill the field with this value. 719 | 720 | required:: 721 | Boolean value indicating whether the field is required. If this is set to `true`, and the user tries to run the script without entering a value for this field, it will show an error and prompt the user to enter a value. 722 | + 723 | .Example 724 | [source,toml] 725 | ---- 726 | required=true 727 | ---- 728 | + 729 | IMPORTANT: Since this is boolean you must use `required=true`, and _not_ `required="true"`. 730 | 731 | type:: 732 | A string indicating the type of widget to use for this field in the dialog. Possible values include "text", "file", "directory", "button", and "checkbox". If this property isn't specified it defaults to "text". 733 | 734 | disposeOnSubmit:: 735 | A boolean option used only on _button_ fields to indicate that the dialog should remain open after the button is pressed, thus allowing the user to, perhaps, run the script again without having to reopen the dialog. Default value is `true`. Set to `false` to cause the window to stay open on submit. 736 | + 737 | .Example 738 | [source,toml] 739 | ---- 740 | [checkServerStatus] 741 | label="Check Server Status" 742 | type="button" 743 | disposeOnSubmit=false 744 | ---- 745 | 746 | [#cli] 747 | == CLI Usage Instructions 748 | 749 | [source,listing] 750 | ---- 751 | Usage: shellmarks [-efhilV] [--as=] [--hash=] [