Skip to content

macmade/ShellKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

75 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ShellKit

Build Status Coverage Status Issues Status License Contact
Donate-Patreon Donate-Gratipay Donate-Paypal

About

Objective-C framework for running shell scripts.

Terminal

Documentation

Documentation and API reference can be found at: http://doc.xs-labs.com/ShellKit/

Code Examples

ShellKit provides a test executable.
For complete examples, please take a look at the source code.

Shell informations

Various shell informations, like paths for commands, can be retrieved using the SKShell class:

[ [ SKShell currentShell ] commandIsAvailable: @"xcodebuild" ] NSString * path = [ [ SKShell currentShell ] pathForCommand: @"xcodebuild" ]

Running simple commands

Arbitrary shell commands can be run using the SKShell class.
Note that commands are executed using the shell defined in the SHELL environment variable, invoked as a login shell.
Data for stdin can be provided; stdout and stderr can be retrieved.

[ [ SKShell currentShell ] runCommand: @"ls -al" completion: ^( int status, NSString * output, NSString * error ) { NSLog( @"%i", status ); NSLog( @"%@", output ); NSLog( @"%@", error ); } ];

Running shell script tasks

A shell command can by run by using the SKTask object:

SKTask * task; task = [ SKTask taskWithShellScript: @"ls -al" ]; [ task run ];

The task is run synchronously, and its output, if any, will be automatically printed to stdout.

The task will print the executed command prior to running, and print a status message once it's terminated, along with the elapsed time:

[ ShellKit ]> 🚦 Running task: ls -al total 536 drwxr-xr-x 5 macmade staff 170 May 11 23:49 . drwxr-xr-x@ 4 macmade staff 136 May 11 22:18 .. -rwxr-xr-x 1 macmade staff 124624 May 11 23:49 ShellKit-Test drwxr-xr-x 7 macmade staff 238 May 11 23:48 ShellKit.framework -rw-r--r-- 1 macmade staff 143936 May 11 23:48 libShellKit-Static.a [ ShellKit ]> βœ… Task completed successfully (63 ms) 

A task can have sub-tasks, to try to recover from a failure:

SKTask * task; task = [ SKTask taskWithShellScript: @"false" recoverTask: [ SKTask taskWithShellScript: @"true" ] ]; [ task run ];

Here, the false task will obviously fail, but it will then execute the true task, set as recovery.
As true will succeed, the false task will also succeed:

[ ShellKit ]> 🚦 Running task: false [ ShellKit ]> ⚠️ Task failed - Trying to recover... [ ShellKit ]> 🚦 Running task: true [ ShellKit ]> βœ… Task completed successfully (66 ms) [ ShellKit ]> βœ… Task recovered successfully (66 ms) 

Optional tasks

A task can be marked as optional by using the SKOptionalTask.
In such a case, the task will succeed, regardless of its exit status:

SKOptionalTask * task; task = [ SKOptionalTask taskWithShellScript: @"false" ]; [ task run ];
[ ShellKit ]> 🚦 Running task: false [ ShellKit ]> ❌ Error - Task exited with status 1 [ ShellKit ]> βœ… Task is marked as optional - Not failing 

Running task groups

Multiple tasks can be grouped in a SKTaskGroup object:

SKTask * t1; SKTask * t2; SKTaskGroup * group; t1 = [ SKTask taskWithShellScript: @"true" ]; t2 = [ SKTask taskWithShellScript: @"true" ]; group = [ SKTaskGroup taskGroupWithName: @"task-group" tasks: @[ t1, t2 ] ]; [ group run ];

The group will try to run each task.
If a task fails, the whole group will also fail.

[ ShellKit ]> [ task-group ]> 🚦 Running 2 tasks [ ShellKit ]> [ task-group ]> [ #1 ]> 🚦 Running task: true [ ShellKit ]> [ task-group ]> [ #1 ]> βœ… Task completed successfully (64 ms) [ ShellKit ]> [ task-group ]> [ #2 ]> 🚦 Running task: true [ ShellKit ]> [ task-group ]> [ #2 ]> βœ… Task completed successfully (65 ms) [ ShellKit ]> [ task-group ]> βœ… 2 tasks completed successfully (132 ms) 

Running task groups within task groups

A task group may also contain other task groups:

SKTask * t1; SKTask * t2; SKTaskGroup * g1; SKTaskGroup * g2; t1 = [ SKTask taskWithShellScript: @"true" ]; t2 = [ SKTask taskWithShellScript: @"true" ]; g1 = [ SKTaskGroup taskGroupWithName: @"child-group" tasks: @[ t1, t2 ] ]; g2 = [ SKTaskGroup taskGroupWithName: @"parent-group" tasks: @[ g1 ] ]; [ g2 run ];

The hierarchy of groups will be reflected by the prompt, like:

[ ShellKit ]> [ parent-group ]> [ #1 ]> [ child-group ]> [ #1 ]> 🚦 Running task: true 

Note that task groups can also run custom classes, as long as they conform to the SKRunableObject protocol.

Variables substitution

A task may contain variables, that will be substituted when running.
A variable has the following form:

%{name}% 

The variable name may contain letters from A to Z (uppercase or lowercase) and numbers from 0 to 9.

Variables are passed using the run: method of SKTask and SKTaskGroup.

SKTask * task; task = [ SKTask taskWithShellScript: @"ls %{args}% %{dir}%" ]; [ task run: @{ @"args" : @"-al", @"dir" : @"/usr" } ];

In the example above, the executed script will be: ls -al /usr.

If no value is provided for a variable, the task will fail:

SKTask * task; task = [ SKTask taskWithShellScript: @"echo %{hello}% %{foo}% %{bar}%" ]; [ task run: @{ @"hello" : @"hello, world" } ];
[ ShellKit ]> 🚦 Running task: echo hello, world %{foo}% %{bar}% [ ShellKit ]> ⚠️ No value provided value for variable: foo [ ShellKit ]> ⚠️ No value provided value for variable: bar [ ShellKit ]> ❌ Error - Script contains unsubstituted variables 

Printing messages

Messages can be printed very easily.
For this purpose, the SKShell class provides several methods, like the following one:

- ( void )printMessage: ( NSString * )format status: ( SKStatus )status color: ( SKColor )color, ...;

The status represents an optional icon.
Colors can also be used, if the terminal supports it.

As an example:

[ [ SKShell currentShell ] printMessage: @"hello, %@" status: SKStatusDebug color: SKColorCyan, @"world" ];

will produce:

🚸 hello, world 

Customising prompt

The prompt can be customised to reflect the hierarchy of the invoked commands.

For instance:

[ SKShell currentShell ].promptParts = @[ @"foo", @"bar" ];

Then, every printed message will be prefixed by:

[ foo ]> [ bar ]> ... message ... 

License

ShellKit is released under the terms of the MIT license.

Repository Infos

Owner: Jean-David Gadina - XS-Labs Web: www.xs-labs.com Blog: www.noxeos.com Twitter: @macmade GitHub: github.com/macmade LinkedIn: ch.linkedin.com/in/macmade/ StackOverflow: stackoverflow.com/users/182676/macmade 

About

Objective-C framework for running shell scripts.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published