Skip to content

Sub sub commands #37

Open
wants to merge 23 commits into from

6 participants

@jeffreyroberts

Let me know if there is anything I can do, add, remove, etc..

It's solid, give it a test drive, it rocks

Fixes #7
Fixes #12
Fixes #16
Fixes #22
Fixes #27

Example Multi-level autocompletion for --complete: Fixes #7

[ /sub ] $ sub example advanced fix-7
bar  foo
[ /sub ] $ sub example advanced fix-7 foo b
baz  bla

Nested "sub-sub-commands": Fixes #22

.
├── bin                               # contains the main executable for your program
├── completions                       # (optional) bash/zsh completions
├── libexec                           # where the subcommand executables are
├───> sub-command                     # sub command (Displays summary for b & c)
|  ├────∎ sub-command-b               # sub command command-b <args>
|  └────∎ sub-command-c               # sub command command-c <args>
└── share 

Example Directory and File Structure: Fixes #22

.
├── bin                               # Real Life Example
├── completions                       # Directories return help for children
├── libexec                           # 
├───> sub-example                     # sub example (Returns summary)
|  ├────> sub-basic                   # sub example basic (Returns summary)
|  |   ├────∎ sub-foreach             # sub example basic foreach (Script)
|  |   └────∎ sub-files               # sub example basic files (Script)
|  └────> sub-advanced                # sub example advanced (Returns summary)
|      └────> sub-expert              # sub example advanced expert (Returns summary)
|          └────∎ sub-case-select     # sub example advanced expert case-select (Script)
└── share 

Example For Directory Help Helper File: Fixes #22

├── libexec                           # 
├───> sub-example                     # sub example (Returns help for example)
|  └───∎ sub-example                  # Provides area for usage, summary, and help

Example Help Helper File: Fixes #22

#!/usr/bin/env bash
# Usage: sub example
# Summary: Collection of BASH Sub Example Scripts
# Help: These commands are mostly used as examples and for testing sub modifications

set -e

sub help example
exit

Example Help Display With sub-sub-commands: Fixes #22

[ /sub ] $ sub help
Usage: sub <command> [<args>]

Some useful sub commands are:
   commands     List all sub commands
   -> example   Collection of BASH Sub Example Scripts

See 'sub help <command>' for information on a specific command.

Example Multiple Command w/ Completion: Fixes #22 & Fixes #12

[ /sub ] $ sub example advanced expert case-select --
--break  --name

Example Multiple Commands and Flags: Fixes #22

[ /sub ] $ sub example advanced expert case-select --break 3 --name Jeff
-=> Executing Case Select Example
----> Breaking on 3
----> Counter is called Jeff
------> The Jeff is 0
------> The Jeff is 1
------> The Jeff is 2
- Finished...

Example File Completion: Fixes #16 & Fixes #27

[ /sub ] $ sub example basic files
.git/        .gitmodules  README.md    completions/ plugins/     share/
.gitignore   LICENSE      bin/         libexec/     prepare.sh
@jblossomweb

+1

@gregsuskind

+1

@jakeasmith

👍

@sphax3d
sphax3d commented Apr 23, 2013

👍

@jeffreyroberts

Fixed minor typo in auto-completion file

@jdevera
jdevera commented Jun 5, 2013

I'm running this as several levels of subcommands are an essential feature for me, so thanks! However I have noticed that the sub-sh-* commands do not work beyond the first level. It seems like the init script has to support that somehow, I just don't know how. Any ideas?

@jdevera
jdevera commented Jun 12, 2013

It seems that replacing _cl_wrapper with this makes the sh-commands work in lower levels:

_cl_wrapper() {
    local pb=$_CL_ROOT/libexec
    local cb
    local cmd=""
    for c in \$@
    do
        if [[ -d \$pb/cl-\$c ]]; then
            pb=\$pb/cl-\$c
            cb="\$cb \$c"
            shift
        elif [[ -f \$pb/cl-sh-\$c ]]; then
            cmd="\$cb sh-\$c"
            shift
        else
            echo command cl \$cb "\$@"
            command cl \$cb "\$@"
            return \$?
        fi

        if [[ -n \$cmd ]]; then
            eval \`cl \$cmd "\$@"\`
            return \$?
        fi
    done
}

However it's barely tested. I have forked the repo and will apply your changes to play a bit with them.

@jdevera
jdevera commented Jun 12, 2013

I also noticed that because the loop that build the command stops when it sees -*, if you pass a positional parameter to an inner scripts, it gets swallowed by the sub.

sub example advanced expert case-select aaa --name

Here cl-case-select only gets --name, not aaa.

@jeffreyroberts

Hey, Awesome stuff, I will take a look at all of this over the weekend =D

@jdevera
jdevera commented Jun 14, 2013

I also wonder about the rationale for moving completions to sub-command.

@jdevera jdevera commented on the diff Jun 14, 2013
libexec/sub-commands
fi
- elif [ -n "$nosh" ]; then
- if [ ${command:0:3} != "sh-" ]; then
+ elif [ "$command" == "commands" ] && [ "$command" == "$_SUB_COMMAND_FILE" ]; then
@jdevera
jdevera added a note Jun 14, 2013
[ "$command" == "commands" ]

That condition can now never be true, since $command is always going to be a path with "/sub-" in it.

Very good call =]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jdevera jdevera commented on the diff Jun 14, 2013
libexec/sub-commands
{ for path in ${PATH//:/$'\n'}; do
for command in "${path}/sub-"*; do
- command="${command##*sub-}"
@jdevera
jdevera added a note Jun 14, 2013

I don't fully understand what is being achieved here, perhaps add some comments explaining what's going on? Something like what are the cases where we want to show the commands and where we don't.

I will def add some comments, I am going to work on this for a couple of hours now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jdevera
jdevera commented Jun 20, 2013

Just for fun, I gave this a go and used a different implementation to support multi level sub commands. My conclusion is that a) it's a mess b) It gets complex enough that it warrants using a more suitable language. So I'm thinking of writing this in python before adding some of the ideas I've had while developing.

I won't open a pull request because it makes no sense to me since there is this one already, but you can take a look at it here: https://github.com/jdevera/sub/tree/subsub

@jdevera
jdevera commented Jun 27, 2013

I ended up rewriting the whole thing in python because it got too big for shell scripting.

Here it is: https://github.com/jdevera/sub/tree/python in case someone wants to give it a go.

I implemented all the default commands internally so I could reuse code and the sub script itself no longer needs to have its guts changed by sed, since it will pick up the sub name from the name of the file itself.

I also changed the shell wrapper so that the script itself is responsible for determining if certain command is an 'sh' command or not.

I added a ton of logging that can be enabled by running with the SUBDEBUG variable set to something.

The direction I'm headed now is to implement what I call "thin subs". The idea is that the sub core lives in one place, and the user's subs live in another, so you can keep the core updated and get the benefits in all your subs, and you don't have to check the core in with your scripts if you don't want to.

If anybody wants to give it a go, you are very welcome, remember I haven't yet merged it to master, so you'll need to checkout the "python" branch after cloning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.