Discussions about the G'MIC script language

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

It would be great to have an editor which makes scripting faster, but it doesn’t seem likely. Even the notepad++ language file I made a while back was hugely out of date in a matter of months. If somebody could both write it then maintain it we’d be ok. Personally I find either “shell” or “R” highlighting does a reasonable job with g’mic code.

@David_Tschumperle
I was just thinking about reducing barriers to creating a custom command in a text file. I know we have a template.gmic in the repo already, but perhaps a command to generate a very small example .gmic file would be good (and perhaps less intimidating)? Is there such a thing already?

Edit: this made me laugh

gmic h example
[gmic] No help available for command 'example'; did you mean '_sample' ?.

gmic h _sample
[gmic] No help available for command '_sample'; did you mean '__sample' ?.

gmic h __sample
[gmic] No help available for command '__sample'; did you mean '_sample' ?.

There is not such a thing, but this is a good idea.

Ah, yes that is because the commands _sample and __sample actually exist, so there become suggestions for valid commands, but they are not documented :slight_smile:

Side note: I’ve added a page in the reference documentation, about the G’MIC Markdown syntax, used to write the documentation (commands included) : https://gmic.eu/reference/g_mic_markdown_gmd_.html

I guess this may be useful. Actually, I’d like to use it to create more documentation pages in the future. Maybe a ‘code snippets’ page, as suggested by @afre ?.

My two pence.
Expanding GC’s third bullet of his first reply: (goal: let readers understand a written G’mic script)
a) have a first code formatter which split lines which have more then one command.
result: a text with one command per line
b) have a second code formatter which “expands” each synthetic command onto a full form command
result: a text with one full (i.e.expanded) command per line
c) have a third code formatter which “interprets” each command and add a comment explaining what that command does
result: a text whith one full command per line followed by one or more lines of “explanations” of what it does
If a newbie could launch these service programs when (s)he wants to understand an existing script, it could be that (s)he will have the desire to try writing some new code.
Difficult? IDK, but I don’t think so. And that could help more than a 500 pages tut, maybe .

1 Like

This question is directed to @afre , @David_Tschumperle, @Iain and @garagecoder, as well as a few more gmic developer.

Do you use word-wrapping and should it be a standard to use long line of text? I know new users might find these a bit intimidating at first as they may not have a decent text editor which is why I asked. I use a mix of word-wrapping as well as disabling it when coding. Makes things a lot easier for me, but I definitely understand why others would not want to do the same.

Here are some lines I refer to:

Line 1: mode=${arg\ 1+$mode,bw,rgb,b_rgb,bw_rgb,cmy,cmyk,wcmyk,rgbcmy,1bitrgb,aurora,playpal,srb2,famicube,kens16,kens32,kens54,aap12,aap16,aap64,aap128,db8,db16,db32,db_iso22,dimwid17,dimwid23,edg4,edg8,edg16,edg32,edg36,edg64,juicy32,juicy56,xaiue,15pdx,20pdx,24pdx,cabana64,fant16,fant24,tf23,tfp39,faraway48,fleja_m,koni32,linearbasic,vinelinear,arcade29,arq16,blk36,blkneo,brokefac,bubblegum,cade15,calder8,chrom16,cdbac,cgarne,cpcboy,dino,4l,fzteth16,gzxp,indc,island16,journey,juice,oak,nature55,nauris16,pear36,peach,pineapple32,resurrect,rosy42,slso,softy15,spec12,starmancer,sup8,superfuture,sweetie16,taffy16,todayland,vivid17,voodo,zu32,enos16,undertones,equpix15,night16,star29,star34,stilllife,simjpc16,acid15,battery24,clump18,cthul,crimso11,coptec,drz15,eggy15,eroge,europa,greyt,jewel,polar11,sheltzy,rube_goldberg,boomboom,g8,matriax8c,nt1h,au15,au15y,jerrypie22,naji16,blessing,crayola,easter,fairy,fuzz4,xdb_01,ocaso,pastel,pastel17,pollen8,nopal,sy17,syz15,tui15,cave,psygnosia,marshmellow32,rabbit7,finlal11,vinik24,ykb22,graveyard,steamlords,aaprad,aapmaj,daruda,rust6,xaiue_rad,firestorm,supernova7,nyx8,oil6,sgm,fornaxvoid1,fornaxvoid2,pixelwave,spaceyeaster,moon39,pet8,pet8d,autochrome3,autochrome5,gb_d_1,gb_d_2,gb_andrade,gb_blue,gb_bz,gb_crimson,gb_didi,gb_dirty,gb_arne,gb_easy,gb_forest,gb_hg,gb_lg,gb_nostalgia,gb_platinum,gb_kirokaze,gb_pj,gb_cyber,gb_wish,gb_grapefruit,gb_ice_cream,gb_rb,gb_space,gb_choco,gb_purpdawn,gb_gray,arne4,hal4,amiga2600ntsc,amiga2600pal,amiga2600secam,amiga7800mess,amiga7800,amstrad_cpc,apple2,cga,cga00,cga01,cga10,cga11,cga20,cga21,c64_pepto,c64_colodore,com_vic_20,colecovision,jmp,mac2,nes,pico_8,risc,samcoupe,mo5,vga,zx,gnome32,elc22,chip16,msx,deluxepaint,lms,msxp,vis}

Line 2: #@gui :Palette=choice(0,"RGB-{3}","B-RGB-{4}","BW-RGB-{5}","CMY-{3}","CMYK-{4}","W-CMYK-{5}","RGBCMY-{6}","1-Bit-RGB-{8}","Aurora-{256}","PLAYPAL-{249}","Sonic Robo Blast 2-{256}","Famicube-{64}","Andrew Kensler - 16","Andrew Kensler - 32","Andrew Kensler - 54","AAP-Micro 12","AAP-16","AAP-64","AAP-SPLENDOR128","DB8","DB16","DB32","DB-ISO22","DimWiddy 17","DimWiddy 23","Endesga-4","Endesga-8","Endesga-16","Endesga-32","Endesga-36","Endesga-64","Juicy-32","Juicy-56","XAIUE-22","15P-DX","20P-DX","24P-DX","Cabana-64","Fantasy 16","Fantasy 24","Tranquil Fantasy 23","Tranquility Plus 39","Faraway 48","Fleja Master Palette-{33}","Koni32","Linear Color Palette Basic-{31}","Vines Flexible Linear Ramps-{38}","Arcade Standard 29","ARQ16","BLK 36","BLK-NEO-{46}","Broken Facility","Bubblegum-16","Cade 15","Calder 8-{11}","Chromatic16","CD-BAC-{16}","CG Arne-{16}","CPC BOY-{32}","Dinoknight 16","||||-22","FZT Ethereal 16","GZXP-{11}","Indecision-{17}","Island Joy 16","Journey-{64}","Juicy 17","Oak21","Nature's Embrace 55","Nauris-16","Pear 36","Peachy Pop 16-{16}","Pineapple 32","Resurrect 32-{32}","Rosy 42","SLSO-CLR17","Softy 15","SPEC12","Starmancer-{52}","Superb 8","SuperFuture25","Sweetie 16","Taffy 16","Todayland Palette V2-{25}","Vivid-17","Voodo34","Zughy 32","ENOS16","Undertones-17","Equpix 15","Night 16","Star 29","Star 34","Still-Life-{14}","SimpleJPC-16","Acid 15","Battery 24","Clumpy 18","Cthulhu-{16}","Crimso 11","Copper-Tech-{16}","DRZ15A","Eggy 15","Eroge-Copper","Europa 16-{16}","GreyT-bit-{8}","Jewel-{15}","Polar 11","Sheltzy 32","Rube-Goldberg-{9}","BoomBoom-{7}","Generic-8","Matriax8c","NT1H-{26}","Autum 15","Autum 15 [Yellow]","JerryPie 22","Naji 16","Blessing-{5}","Crayola Blind-{9}","Easter Island-{16}","Fairy Tales-{8}","Fuzzy Four-{4}","0xdb-01-{17}","Ocaso-{17}","Pastel-{15}","17 Pastels","Pollen-8","Nopal-12","Sy17","Syz15","TUI-15","Cave-{8}","Psygnosia-{16}","MarshMellow32","Rabbit 7","Finlal 11","Vinik 24","YKB-22","Graveyard-21","Steam Lords-{16}","AAP-RadiantXV-{15}","AAP-Majesty XVII-{17}","Daruda 22","Rust-6","XAIUE-Radiant-{22}","Firestorm-{9}","SuperNova 7","NYX8","OIL6","SGM-Palette 2-{17}","Fornax Void I-{256}","Fornax Void II-{128}","Pixelwave-{12}","Spacey Easter-{17}","Moonlit-39","Petite-8","Petite-8 Afterdark","Autochrome 3","Autochrome 5","GB Default #1-{4}","GB Default #2-{4}","GB Andrade-{4}","GB Blue Seni-{4}","GB Blackzone-{4}","GB Crimson-{4}","GB Didi-{4}","GB Dirty-{4}","GB Arne-{4}","GB Easy-{4}","GB Forest-{4}","GB Harsh Green-{4}","GB Light Green-{4}","GB Nostalgia-{4}","GB Platinum-{4}","GB Kirokaze-{4}","GB PJ-{4}","GB Cyber-{4}","GB Wish-{4}","GB Grapefruit-{4}","GB Ice Cream-{4}","GB Red_Blue-{4}","GB Spacehaze-{4}","GB Chocolate-{4}","GB Purple Dawn-{4}","GB Gray-{4}","ARNE4","HallowPumpkin-{4}","Amiga 2600 NTSC-{128}","Amiga 2600 PAL-{104}","Amiga 2600 SECAM-{8}","Amiga 7800 M.E.S.S-{256}","Amiga 7800-{256}","Amstrad CPC-{27}","Apple II-{15}","CGA-{16}","CGA Mode 0 [Low]-{4}","CGA Mode 0 [High]-{4}","CGA Mode 1 [Low]-{4}","CGA Mode 1 [High]-{4}","CGA Mode 2 [Low]-{4}","CGA Mode 2 [High]-{4}","Commodore 64 [Pepto Interpretation]-{16}","Commodore 64 [Colodore Interpretation]-{16}","Commodore VIC-20-{16}","Colecovision-{15}","Japanese Machine Palette-{16}","Macintosh II-{16}","NES-{52}","PICO-8-{16}","RISC OS-{16}","SAM Coupe-{128}","Thomson MO5-{16}","VGA-{244}","ZX Spectrum-{15}","GNOME 32-{32}","Electronic Crayon 22","Chip16","MSX-{15}","Deluxe Paint-{222}","Legacy Paint-{16}","XP Paint-{28}","Vista Paint-{28}")

Normally, I would do a hard wrap with indentation. If it is a long list of items, I would keep it in one line (or separate into 2 max), since it is easy to tell that it is just one long list of items. Perhaps, to make it more readable, include a reference to an end note listing all of the modes or choices offered in documentation form. More importantly, your help should be readable.

In general, do what looks good. Make it more readable than you think it should be. We have all encountered the scenario where we leave a piece of code alone and not be able to decipher it when we return. Means we didn’t do a good job in the first place.

I don’t use long lines at all. I prefer to deal with multi-lines, eventually by inserting a \ at the end of the line to say the line does not stop, but continue with the following line.

I’m fairly flexible with it, but do have the line break column indicator in Geany set to 80. I do allow some of the gui definition lines to extend quite far though.

I don’t because I don’t want to manage \ whenever I change the line.

I set mine at 70 columns.

Mine is set to 80. Also, ditto on the managing \.

Instead of \, I make a new #@CLI or #@GUI line, or use quotes.