String arguments for custom function

If I have a custom function

foo:
  echo ${1=def1}
  echo ${2=def2}

how do I pass a string with a space to the function? gmic foo "test string","no string" does not work… This must be really easy…

Yes, you have to keep in min that $1 in a command is substituted by its value, so
echo $1 can be substituted by echo Hello World , which is not correct, as it tells that the argument of echo is Hello, then it will interpret World as the name of another command to execute (or a filename to load).
Correct syntax is:

foo : 
  echo "${1=def1}"
  echo "${2=def2}"

To be more precise, there can be confusion because the way $1,$2,.. and variables like $var are substituted is actually very different:

  • When you invoke a command, the interpreter instantiates that command, with the actual arguments given. This means the interpreter basically copy/pastes the command code where all expressions as $1, $2,… have been replaced by the value of the given arguments. This operation is done before executing the command, that’s why it’s not possible to re-assign values for $1, $2,… during command execution.
    Those are simply not variables! Once the code of a command is instantiated, they do not appear anymore in the command code. They have already been replaced by their contents when the interpreter starts executing the command.

  • On the other hand, variables like $var are substituted during the execution of the command (not its instantiation). That’s why they can be re-assigned during a command execution.

The subsitution rules for these two different objects are slightly different: while patterns like $1,$2,… are substituted everywhere they appear during the command instantiation (particularly, they are replaced even inside strings), it’s not the same for regular variables.

So, for instance:

foo :
  echo "$1"
  var=$1
  echo "$var"

called with

$ gmic foo Hello

will display :

Hello
$var
2 Likes

Thank you, @David_Tschumperle!

Hmm…
gmic foo "hello my","world" results in

[gmic]./ Start G'MIC interpreter (v.3.3.1).
hello my,world
def2

Why is “world” not on the second line (instead of def2)?

Is there any reason why you don’t use \n ?
I think it works.

I got different result with using \ as escape char.

C:\Windows\System32>gmic foo \"hello my\",world
[gmic]./ Start G'MIC interpreter (v.3.3.1).
hello my
world
[gmic]./ End G'MIC interpreter.

With just ", it treats everything between first and last line as " and ignores the " inside them within Windows. This isn’t a G’MIC issue, but a CLI issue.

Does it work with gmic run '...' and no escape ?

There are actually no issues, just a set of rules that has to be known :slight_smile:

  • Before all, remember that G’MIC is a programming language, just as bash, so if you want to write “more-than-basic” scripts from a shell (I mean G’MIC scripts that requires special characters as \ or "), prepare yourself for some headaches in your first experiments, because you’ll need to take into account both the syntax of bash and G’MIC at the same time. That’s definitely harder than just writing your G’MIC script in a .gmic file.

  • In a shell, if you write an item with a space in it, it is automatically detected as a double quoted string in G’MIC. So:

foo :
  echo "$1"

and

$ gmic foo "This is a single item"
[gmic]./ Start G'MIC interpreter (v.3.3.1).
This is a single item
[gmic]./ End G'MIC interpreter.

Note that even if the argument contains a , it won’t be split into multiple arguments. An item with a space put on the command line will be all put into $1.
This rule applies mainly because if you want to just input an image file with a space in the filename, then you can just call its like:

$ gmic "Filename with space.jpg"

and not

$ gmic \"Filename with space.jpg\"

(though the second version should also work).

  • If you need to specify multiple arguments to a command, where some of them have spaces in it, just backslash the double quotes:
foo :
  echo "$1"
  echo "$2"

then, call it like this:

$ gmic foo \"This is the first item\",\"This is the second one\"
[gmic]./ Start G'MIC interpreter (v.3.3.1).
This is the first item
This is the second one
[gmic]./ End G'MIC interpreter.

I think that with these two examples, it should be enough for you to master now G’MIC scripting from the shell :slight_smile: