Discussions about the G'MIC script language

I don’t understand what you are trying to achieve here. Could you tell a bit more details ?

The same trick I gave to @garagecoder two days ago also applies here:

eval "
   tab = vector(#3*100);                   # Array of 100 vectors of size 3.
   tab_get(p) = tab[3*p,3];                # Get vector3 at position tab[p].
   tab_set(p,vec) = copy(tab[3*p],vec,3);  # Set vector3 at position tab[p].

That’s mainly because the return value of all expressions in the math evaluator can be theoretically assigned to a variable. And the type of a variable must be known at compilation time. Obviously,

eval "
   X = if (u<0.5, pi, vector3());
"

won’t let the compiler decide what is the type of X.

I’m sorry to hear that :frowning: I don’t want to be responsible for the time you waste during the day!

Yes, you’re right, documentation is not enough detailed at the moment.
I don’t really know how I can improve that by the way. I’m not a really good documentation writer TBH.

On #1, it about assigning expressions to func(). To do that dynamically, I have to use if func_string=expr elif func_string=expr2 outside of fill. Then, assign func_string to func().func(a,b,c) can be changed within fill, eval…

On #2, trick noticed.

On #3, I acknowledge why. Just saying that it would be easier if it wasn’t a requirement though that’s not possible to do. In other programming language, if else can take just about any arguments.

Something like this could work, maybe ?

foo :
  eval "
    $1?(
      func(x) = 3*x;
    ):(
      func(x) = pi + x;
    );

    print(func(5));
  "

and then:

$ gmic foo 0
[gmic]-0./ Start G'MIC interpreter.
[gmic_math_parser] func(5) = 8.1415926535897931
[gmic]-0./ End G'MIC interpreter.
$ gmic foo 1
[gmic]-0./ Start G'MIC interpreter.
[gmic_math_parser] func(5) = 15
[gmic]-0./ End G'MIC interpreter.

EDIT: this will work as long as the checked expression is a constant (here $1).

Gonna move the discussion to my g’mic thread since now it’s going offtopic.

For this, I have a possible solution :

def_enum_resize : 
  _i_memory,_i_none,_i_nearest,_i_average,_i_linear,_i_grid,_i_bicubic,_i_lanczos=-1,0,1,2,3,4,5,6
  _b_dirichlet,_b_neumann,_b_periodic,_b_mirror=0,1,2,3

foo : 
  def_enum_resize
  resize[0] 256,256,1,3,$_i_none,$_b_mirror

It’s actually quite the same as using enum in C when defining function arguments. Personnally, I don’t like it that much.

I might then write:

resize[0] 256,256,1,3,$_b_mirror,$_i_none

… with the interpolation and boundary parameters inverted. The interpreter would not flag my mistake.

In my opinion, the interpreter should accept one of the following for boundary: 0 1 2 3 dirichlet neumann periodic mirror.

Anything else should be rejected.

Ideally it would not accept the numbers, but that would break existing scripts, so is not a feasible solution.

Then, this command basically does the trick:

resize_with_enum : skip ${2=100%},${3=100%},${4=100%},${5=nearest},${6=neumann},${7=0},${8=0},${9=0},${10=0}
  resize ${1-4},\
    {s=['$5'];s=='memory'?-1:s=='none'?0:s=='nearest'?1:s=='average'?2:s=='linear'?3:s=='grid'?4:s=='cubic'?5:s=='lanczos'?6:nan},\
    {s=['$6'];s=='dirichlet'?0:s=='neumann'?1:s=='periodic'?2:s=='mirror'?3:nan},\
    ${7-10}

and then:

$ gmic sp colorful resize_with_enum 200%,200%,1,3,none,mirror

The code snippets idea would be crowd supported, so the onus won’t have to be on you. I will give you an example, based on 1 of thousands of questions I asked you.

# foo_by demonstrates CLI echoing and one kind of substituting.
# Outputs the message: 'Filter with a 3x3 filter'.
# Note. Without the { }, we get: 'Filter with a 3 filter' instead.
foo_by:
  t=3 e[^-1] "Filter with a "${t}"x"${t}" filter"

I think that’s a good demonstration of the “macro” problem. On the one hand, we have a very flexible way to redefine commands to work how we please. But on the other, it’s (much?) more difficult for people other than yourself to do so!

Some elements of g’mic are practically like bash or even regular expressions, so it’s hard to reconcile power with simplicity.

That’s true, and somehow intended.
G’MIC being a script language, it has been inspired a bit from bash (and also a bit from sed).
But is there any script language that do not have this kind of expressions ?
(don’t anwer perl :slight_smile: ).

Speaking of substitution, (at least) two pages talk about it, not one:
G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Substitution Rules
G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Adding Custom Commands

I know I originally asked the documentation to be separated into separate manageable chunks but it can in some ways make searching for the relevant info more difficult. I am still waiting for a search function with suggestions. :crossed_fingers:

Before, when commands and examples were quoted or more distinct than CSS styles, they were easier to find using the browser search. E.g., when ‘resize’ was quoted like this or something like that, I could find it in a heartbeat without going through all the times the word appeared in the document. I mentioned this before but styled text also interferes with screen readers and other aids that people with disabilities use.

On documentation:
It’s a living thing, just like the code. We could add loads of examples etc. but in the end lots of documention becomes a problem too if it’s not well organised and maintained. Not sure how we solve that.

Back to code & language style:
I suppose obscure syntax is totally fine if that suits the target audience and purpose. I have to say it does suit me, up to a point.

It might be worth considering which very commonly used parts could be made more descriptive or obvious though. Could the image count be represented by something other than just $!? Could the default loop counter be something other than $>? Changes to those would probably irritate me actually!

I think that adding options to use non-symbol version of those would be great to have. But, that’s only because it’ll help reduce reliance on symbols for new users.

A snip from reptorian.gmic.

if s#$><3||s#$>>4 error s#{$>}>2&&s#{$>}<4==F fi

Another snip

temp_tile_width={floor(w#$>>h#$>?$non_zero_length:w#$>/h#$>*$non_zero_length)}

I can see that some users would be going like, huh, what does this mean?

Back to documentation :stuck_out_tongue:: here is one example of documentation that I find compelling. Note that I am only a beginner at LilyPond and so the documentation is especially helpful to me. It subdivides documentation in terms of depth, usage and examples, with code, description and visuals on every page. Besides official snippets, it also has a repository of user submitted snippets. Lastly, it has unit / regression testing examples to ensure commits don’t introduce bugs or have unintended consequences.

http://lilypond.org/manuals.html

An idea not quite related to the language itself, but might solve some problems.

Years ago I played around with video processing scripts with AVIsynth. There was an editing program that helped in the script writing process that had a number of useful functions, like syntax highlighting etc.

A really useful one was something like auto-complete. IIRC once you had typed in a command it would give you a list of the variables it expected, and I think it even provided menus when there were discrete choices.

So I think having a simple editor that can help the user write scripts would help a lot of people and make it easier to learn.

1 Like

I personally use KDE Kate for gmic scripting. Not quite perfect, but it is the best option I have. What would be nice is to have a gmic-qt highlighting for KDE Kate. I would actually use commentaries more often there to explain to users how the code works.

The thing about this thread is that most of these ideas have been proposed before. It is just a matter of having the will to begin these projects. I offer the snippets / Wiki one because it is doable.

In contrast, syntax highlighting, convenience fills, variable and function management, and reference retrieval will require much more effort and coordination to pull off. Not that it can’t be done. It is a matter of selecting a standard and working on the definitions and conditions.

That is something I’ve already thought of: having longer names for the few obscure G’MIC “variables”, like $!, $|, etc.
For example, we could allow “long” names like $size (for $!) and $time (for $|), and then these variables would also have short names, like commands.

Pros:

  • Make the code more readable.
  • Does not break the existing code (apart if variables $size or $time were already used in a command implementation).

Cons:

  • It would concern only a few variables $!, $>, $<, $/, $| and $^ (so 6 items in total, 3 of which are used very rarely: $/, $| and $^). It would not solve the readibility problem for the other substituting expressions (e.g. {0,@1--1:2}). And for those, I don’t think it’s easy to have a similar “equivalent long syntax”.
  • These particular “variables” have been named like this specifically not to be confused with “usual” variables. Obviously, they don’t behave exactly like classical variables : they cannot be assigned and their value may change over time (while not being assigned). Other “pre-defined” variables in G’MIC, with more common names, such as $_cpus, $_path_rc,… can be actually re-assigned by the user without any problem.

So at the end, I’m not sure it is worth having two different names (one long, one short) for, e.g. $! or $>, not saying that mixing those names could be even worse in terms of code readability.

Maybe it could be interesting to have a more “verbose” way of expressing more general substituting expressions, but here again, it seems to be a quite challenging task.

Here is an extreme example, but for instance, how would do have a somehow short and readable syntax for something as {img,@0-50%:4:" "}, which actually means “the list of values from image [img], separated by whitespaces, and corresponding only to the first half of the image value but with a step size of 4” ?

The current syntax of G’MIC substituting expression is indeed quite complex, but extremely powerful and versatile, and I don’t know how we could simplify that for the user.

In that case, I think formatting your code could already help:

if !inrange(s#$>,3,4)
  error "Condition: "s#$>">=3 && "s#$>"=<4 does not hold."
fi

and

temp_tile_width={i=$>;"floor(w#i>h#i ? "$non_zero_length":w#i/h#i*"$non_zero_length")}"

Also remember that you can always name a loop variable in command repeat:

repeat 20,i
  e[] "i = "$i
done

So that you don’t have to use $> all the time (it is just a defaut name for the current loop counter).

On Linux actually, we have a bash-autocompletion script for G’MIC, which allows to use Tab on the command line when typing a command, and get auto-completion and list of possible arguments. This is really useful indeed.
I don’t know how to do that for a text editor however, and I suppose this should be done differently for different editors. What a pain!

See: code snippets are important. Now, I am reminded that I could use inrange() to keep my checks shorter, more organized and easier to read.

1 Like