Write a function in zshrc that can take a parameter and can handle flags

google-chromezsh

I usually need a chrome page opened to localhost:3000 when I am developing. So, I just run the following cmd:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --app=http://localhost:3000

Since I use this frequently and sometimes my port changes. I want to write a function in zsh where ch will open chrome in localhost:3000 while ch 2500 will open chrome in localhost:2500.

So far, this is what I have managed to do:

ch () {
    command "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
}

This opens a new chrome window but displays an error/warning in the console: /Library/Caches/com.apple.xbs/Sources/AppleGVA/AppleGVA-9.1.12/Sources/Slices/Driver/AVD_loader.cpp: failed to get a service for display 3

But when I add a flag:

ch () {
    command "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --app=http://localhost:3000"
}

Nothing happens and I end up getting an error:
ch:1: no such file or directory: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --app=http://localhost:3000

Best Answer

The reason it does not work with the added flag is that you added the flag within the double quotes, essentially telling zsh that it is part of the command name. The only reason any quotes are needed is that the path to and name of Google Chrome contain whitespaces. Whitespaces are used by zsh (and any other Unix shell) as separator between words. Quoting a string tells zsh that it should be interpreted as a single word, no matter how many whitespaces (or other syntactic elements) are in it.

One way to do this correctly is:

ch () {
    "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --app=http://localhost:${1:-3000}
}
  • Here only the path to Google Chrome is quoted, while the flag is separate.
  • The keyword command is not necessary. It would only tell zsh to use an external command instead of a function or alias of the same name, which is most likely not a risk here (The alias or function would have to be named "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
  • ${1:-3000} is substituted with the first parameter ($1) passed to ch. If it is undefined or has a null-value (e.g. "") "3000" will be substituted instead. So running

    ch 2500
    

    will open Chrome on http://localhost:2500, but running

    ch
    

    will open Chrome on http://localhost:3000.