Pass Arguments to zsh Functions with zparseopts

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet

Parsing arguments in zsh functions can be a bit difficult to manage if you try and customize it for each new function. Luckily, that's where zparseopts comes in. zparseopts is a utility function which can parse out each of the arguments you define and store them inside of an associative array for easy access. This makes accessing arguments as easy as looking them up by name.

John Lindquist: [0:00] Create a new file, called greet to store your zsh function, then invoke the zparseopts utility to parse out the arguments. As an example, if I type greeting, and said this takes an argument, and we'll assign it to a variable of g. Then I can echo out g and in my terminal when I load up greet, and invoke greet, you'll see I have a blank line.

[0:25] If I invoke greet with -greeting, and pass in a value, hit Enter, you'll see I have -greeting, and hello. Since, this is a pair and zsh starts at one instead of zero, we'll want to load the second value from it. I'll reload greet, and type in greet, the greeting again, and I'll get the value, hello.

[0:46] You'll notice only a single dash here and the convention for full words is using a double dash and you reserve the single dash for single letters. When we add a dash in front and reload, and run greet again, now, you'll see it fails with a single dash and it requires a double dash.

[1:05] Rather than this syntax, my preferred method is to use an associative array. You do that with -A, and the name of the array. I'll just call it "opts" for options. Then, I can use opts to look up any of the arguments that are stored inside of it. If I echo opts greeting, and I reload, and rerun, you'll see I have "hello" again. Just to confirm this is working, I'll type in "hi," and you'll see "hi."

[1:33] To add another argument, we can do a -name and the colon, so it takes a value. I'll wrap this inside of a string and do comma $opts, and grab the --name. Now, after I reload greet, and I type out --greeting "hi," and --name "John," I'll hit Enter, and you'll see, "hi, John" being printed out.

[1:55] Now, it's common to pass in an argument before you pass in the optional arguments, such as, "Welcome." If I were to try and do this, --greeting "Hi" and --name "John," you'd see the result would be a comma. That's because this is throwing off how these are being parsed.

[2:15] To allow you to do this, we can go ahead and add in a -E. Let's save, reload greet, and run greet, "Welcome" again, and you'll see, "Hi, John." Let's go ahead and add in our "Welcome." This is just $1, since it's the first argument, and we'll reload, and run it again.

[2:34] Now, we have our "Welcome. Hi, John," were "Welcome" is this first argument, and "Hi" was mapped to the --greeting, and "John" was mapped to the --name. Now, if we were to try and do the same thing the other way around where we put the arguments first, like Hi, and name, John, and then a Welcome. I'll hit Enter here and you'll see that the dollar one correctly pulls in --greeting as the first argument, because that's exactly what we passed in.

[3:01] To drop each of these as they are parsed-out so that we can still use dollar one to access this, we can add in the -D. Now, after I reload, and run greet, hit Enter here. You'll see we're back to, "Welcome. Hi, John," because this -D, after these are parsed, drops them so that, "Welcome," now becomes the first argument.