I'm trying to create .awk extension, cloning from Perl/.pl. ### Preamble Cloning `/usr/share/geany/filetype_extensions.conf` to `~/.config/geany/filetype_extensions.conf` and changing line `Perl=*.pl;*.perl;*.pm;*.agi;*.pod;` to `Perl=*.pl;*.perl;*.pm;*.agi;*.pod;*.awk;` allowed awk files to be viewed as perl; that's a start. Now I want to add extra keywords. ### Work Done So I undo the `~/.config/geany/filetype_extensions.conf` Perl changes, add additional line of `Awk=*.awk;` then clone `/usr/shared/geany/filedefs/filetypes.perl` to `~/.config/geany/filetypes.awk`, making relevant changes, and it doesn't work; awk files show as plain text. **What have I done wrong, or overlooked?** My changes were (sorry; compare went backwards): ``` --- /home/xxx/.config/geany/filedefs/filetypes.awk +++ /home/xxx/.config/geany/filedefs/filetypes.perl @@ -1,4 +1,3 @@ -# 2020-07-11 copied from /usr/shared/geany/filedefs/filetypes.perl # For complete documentation of this file, please see Geany's main documentation [styling] # Edit these in the colorscheme .conf file instead @@ -53,20 +52,17 @@ format=string_2
[keywords] -# add awk keywords before NULL __FILE__ -primary=function switch case break default CONVFMT FIELDWIDTHS FS IGNORECASE OFMT OFS ORS RS SUBSEP ARGC ARGV ARGIND ENVIRON ERRNO FILENAME FNR NF NR RLENGTH RSTART RT PROCINFO NULL __FILE__ __LINE__ __PACKAGE__ __SUB__ __DATA__ __END__ AUTOLOAD BEGIN CORE DESTROY END EQ GE GT INIT LE LT NE CHECK abs accept alarm and atan2 bind binmode bless caller chdir chmod chomp chop chown chr chroot close closedir cmp connect continue cos crypt dbmclose dbmopen default defined delete die do dump each else elsif endgrent endhostent endnetent endprotoent endpwent endservent eof eq eval exec exists exit exp fcntl fileno flock for foreach fork format formline ge getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getppid getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep gt hex if index int ioctl join keys kill last lc lcfirst le length link listen local localtime lock log lstat lt m map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct open opendir or ord our pack package pipe pop pos print printf prototype push q qq qr quotemeta qu qw qx rand read readdir readline readlink readpipe recv redo ref rename require reset return reverse rewinddir rindex rmdir s say scalar seek seekdir select semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat state study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unless unlink unpack unshift untie until use utime values vec wait waitpid wantarray warn when while write x xor y +primary=NULL __FILE__ __LINE__ __PACKAGE__ __SUB__ __DATA__ __END__ AUTOLOAD BEGIN CORE DESTROY END EQ GE GT INIT LE LT NE CHECK abs accept alarm and atan2 bind binmode bless caller chdir chmod chomp chop chown chr chroot close closedir cmp connect continue cos crypt dbmclose dbmopen default defined delete die do dump each else elsif endgrent endhostent endnetent endprotoent endpwent endservent eof eq eval exec exists exit exp fcntl fileno flock for foreach fork format formline ge getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getppid getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep gt hex if index int ioctl join keys kill last lc lcfirst le length link listen local localtime lock log lstat lt m map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct open opendir or ord our pack package pipe pop pos print printf prototype push q qq qr quotemeta qu qw qx rand read readdir readline readlink readpipe recv redo ref rename require reset return reverse rewinddir rindex rmdir s say scalar seek seekdir select semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat state study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unless unlink unpack unshift untie until use utime values vec wait waitpid wantarray warn when while write x xor y
[lexer_properties] styling.within.preprocessor=1
[settings] # default extension used when saving files -extension=awk -#extension=pl +extension=pl
# MIME type -mime_type=application/x-awk -#mime_type=application/x-perl +mime_type=application/x-perl
# the following characters are these which a "word" can contains, see documentation #wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 @@ -98,14 +94,12 @@ # %e will be replaced by the filename without extension # (use only one of it at one time)
-compiler=awk -f %f -#compiler=perl -cw "%f" +compiler=perl -cw "%f"
# alternatively use perlcc #compiler=perlcc -o "%e" "%f"
-run_cmd=awk -f %f -#run_cmd=perl "%f" +run_cmd=perl "%f"
# Parse syntax check error messages and warnings, examples: # syntax error at test.pl line 7, near "{ ```
PS I also modified `~/.config/geany/filetype_extensions.conf` with active lines ``` Perl=*.pl;*.perl;*.pm;*.agi;*.pod; ### *.awk; ... [Groups] #~ Programming=Arduino;Clojure;CUDA;Cython;Genie;Groovy;Kotlin;Nim;Scala;Swift; Script=Graphviz;TypeScript;Awk; ```
Custom filetypes are customisations using existing filetype capabilities so no coding is needed.
Couple of problems with your attempts,
1. you create a `filetypes.awk`, but as the manual says about [custom filetypes](https://www.geany.org/manual/current/index.html#custom-filetypes) the file should be `filetypes.Xxx.conf` where Xxx is a case sensitive filetype name. The `filetypes.xxx` ones are built-in and need code support within Geany. Perhaps look at the existing custom ones such as `filetypes.Scala.conf` and see how they relate to the underlying build-in filetype, eg Scala to C. 2. you added `*.awk` to perl, which as I said elsewhere tells Geany that awk files are perl, not what you wanted. The original addition defining a new `Awk` filetype to extension mapping is the right one, but without the `Awk` matching a filename as above being right it won't work, as you found. 3. The `[groups]` stuff tells Geany where to put the custom filetype in the stuffed to the gills filetypes menu, probably needed.
- ,,, but as the manual says about [custom filetypes](https://www.geany.org/manual/current/index.html#custom-filetypes) the file should be `filetypes.Xxx.conf` where Xxx is a case sensitive filetype name.
That's interesting. It doesn't explain why there's a filetypes.perl but no filetypes.perl.conf or filetypes.Perl.conf.
There is a `filetypes.perl` but no `filetypes.Perl.conf` because Perl is a __built-in filetype__, that is it is a base filetype, hard coded into Geany, and not dependent on any other filetype. Its not a custom filetype that depends on another built-in filetype.
For each hardcoded filetype, Geany has code that looks for a `filetypes.xxx` as the filetype is used by a file, but for custom filetypes it searches for all `filetypes.*.conf` files at startup and creates filetypes for each one it finds, so nothing needs to be coded in Geany. The custom filetypes files have a different form from the built-in ones so the built-in ones are not found again by that search since they are in the same directory.
I have found the following filetypes.*.conf: ``` /usr/share/geany/filedefs/filetypes.Arduino.conf /usr/share/geany/filedefs/filetypes.CUDA.conf /usr/share/geany/filedefs/filetypes.Clojure.conf /usr/share/geany/filedefs/filetypes.Cython.conf /usr/share/geany/filedefs/filetypes.Genie.conf /usr/share/geany/filedefs/filetypes.Graphviz.conf /usr/share/geany/filedefs/filetypes.Groovy.conf /usr/share/geany/filedefs/filetypes.JSON.conf /usr/share/geany/filedefs/filetypes.Kotlin.conf /usr/share/geany/filedefs/filetypes.Nim.conf /usr/share/geany/filedefs/filetypes.Scala.conf /usr/share/geany/filedefs/filetypes.Swift.conf /usr/share/geany/filedefs/filetypes.TypeScript.conf /usr/share/geany/filedefs/filetypes.conf ``` * I thought (incorrectly, I hope) that `filetypes.conf` might be some generic skeleton starting point, but it states `# the lexer doesn't support keywords` which is a specific feature that I do want. * I have looked in `filetypes.perl` for some hint as to which lexer it uses, but it doesn't (well, not that I could see). There are arcane references in the manual to some Scintilla lexer but ... I don't see it in that list I just dumped. * Inside `filetypes.perl` there is a cryptic comment `# Edit these in the colorscheme .conf file instead` but, of course .... no indicatiion of which `.conf` file that s. So ... **Where can I found how to A) find out which lexer a builtin filetype uses (specifically `perl`)? B) which `.conf` I should perhaps start with?**
Not sure what `filetypes.conf` is for, I can't find anywhere that Geany reads it, but looking at its history it seems to be intended to be a template for built-in filetypes, maybe, but its not clear??? Anyhow as its not loaded (AFAICT) and not referenced in the documentation so just forget it until someone else can explain its usage (anybody?).
I have looked in filetypes.perl for some hint as to which lexer it uses
Perl is built-in so the lexer choice is hard coded, so nothing is needed in the filetypes file, same for tags parsers. For Perl the lexer [is this](https://github.com/geany/geany/blob/master/scintilla/lexilla/lexers/LexPerl....). The easiest way of telling which lexer/parser a built-in uses should be the filename in this directory, or in the ctags parsers directory.
Lexers come from the [Lexilla](https://github.com/ScintillaOrg/lexilla) and unfortunately their documentation is their code, so properties and numbers of keyword lists need to be gleaned from their code, or for custom filetypes by reading the base filetype file which _should_ be updated if needed every time the lexer is updated.
# Edit these in the colorscheme .conf file instead
See [here](https://github.com/geany/geany-themes)
Before colour schemes were invented the mapping between lexical entities and styles was in the filetypes files, where the comment is, now the filetypes files map lexical entities to named styles and the colour scheme file maps named styles to colours. The intention is that similar entities in all languages would map to the same named colour so users of multiple filetypes would get similar colouring, and colour schemes wouldn't have to have mappings for each filetype, but of course anybody can (mis)configure it in their custom filetype file for their language or the user override for the builtin filetype file.
which .conf I should perhaps start with?
The manual suggests copying the builtin filetype file and adding the `lexer_filetype` and `tag_parser` keys whose value is the builtin filetype name. That will copy the right number of keyword lists and lexical element to named style mappings, but they will override any changes that happen in the builtin in future Geany releases. Or as explained [here](https://www.geany.org/manual/current/index.html#reading-styles-from-another-...) you can get them from the builtin, and then only change ones you actually need to, thats probably preferable.
Custom styles, colour schemes, and various other changes have happened over a long period of time, not all at once, and manual updating is done by the people doing the changes, who totally understand their change, so are brief in the manual and only note their part and not the whole. Also contributors do not always speak English as a first language so again they are brief.
A full tutorial or howto on creating custom filetypes and configuring the filetypes system would be good, but Geany is a totally volunteer project, nobody is paid to do anything, and nobody can be forced to do anything, and so most contributions are things people are capable of, are interested in, or find useful for themselves. So far nobody has seen fit to contribute such a document or to improve the manual.
When, I've taken one step forward, but not in the direction I want. It shows different syntax colours [good; it's recognising .awk as a known language] but not keywords I want [bad]; neither keywords from `filetypes.Awk.conf` nor `filetypes.awk` nor `filetypes.perl`, I have created `~/.config/geany/filetype_extensions.conf` with lines of ``` [Extensions] Awk=*.awk; Perl=*.pl;*.perl;*.pm;*.agi;*.pod; [Groups] None=Awk; ``` I have created `~/.config/geany/filedefs/filetypes.Awk.conf`. with ``` [styling=Perl] primary=NR break switch NULL __FILE__ [... rest just like perl ...] # note three awk keywords prefixing standard perl ones. [lexer_properties=Perl] [settings] lexer_filetype=Perl tag_parser=Perl extension=awk comment_single=# #[build-menu] ```
I have created `~/.config/geany/filedefs/filetypes.awk` based on `filetypes.perl` as shown in original post (I hope). It has dozens of awk keywords.
I have modified `~/.config/geany/filedefs/filetypes.perl` to add a couple of awk keywords `primary=case NR NULL __FILE__ [ ... ]` . Note that when viewing `MyFile.pl`, it shows these perl and new keywords with keyword highlighting. But NOT for MyFile.awk i,e. no perl nor awk keyword highlighting.
Generally looks ok.
In your `filetypes.Awk.conf` you are missing the `[keywords]` header from before `primary=....` so thats likely why it doesn't work.
The `filetypes.awk` will be ignored and is useless, you can delete it.
* Thank you @elextr. You were right about my missing line; must have been too severe in removing stuff from what I used as a template. Also removed the useless file. * It is now up and running, certainly as a 'like perl but a bit different' filetype. * One slight tweak I would like to make, is making `@load` a keyword. I've added it (both `@load` and `load` just in case), and also added to `[settings]` the line `wordchars=_@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` but to no avail. It's not a show stopper issue, but definitely a nice-to-have.
Is `@load` a valid Perl keyword? Remember the lexer is still Perl. I didn't look at its code, but it almost certainly does not use the wordchars list for deciding whats a legal keyword, at least most lexers don't let Geany set that. I think `@something` is a variable in Perl, but its been a long time.
Just a hint, to see what style number the lexer assigns to characters you can add to the status bar template in various preferences (%Y IIRC but RTFineM for details).
Just a hint, to see what style number the lexer assigns to characters you can add to the status bar template in various preferences (%Y IIRC but RTFineM for details).
And that's the problem; the manual merely gives hints, without revealing much e.g. [https://www.geany.org/manual/current/#statusbar-templates%5D(https://www.gea...) . So going to Edit > Preferences > Various > interface.statusbar_template and changing text 'scope' to 'cope' and [Apply] ... does nothing (and I believe that I have followed the manual's instructions - I tried both [Apply] and [OK] buttons); it just ignores my change, which it sets back to what it was, even after restart. There is no indication or documentation (that I could find, that worked) on how to actually change either the statusbar_template, nor what might be an actual statusbar (is it different?).
I guess that we have differences on what the 'F' of RTFM stands for.
s `@load` a valid Perl keyword? Remember the lexer is still Perl. I didn't look at its code, but it almost certainly does not use the wordchars list for deciding whats a legal keyword, at least most lexers don't let Geany set that.
It's crazy, I know, but I was hoping that `geany` would allow customisation of things like `wordchars` and `keywords`. If only there was some feature like a configuration file for each file extension that allowed that.
So going to Edit > Preferences > Various > interface.statusbar_template and changing text 'scope' to 'cope' and [Apply] ... does nothing (and I believe that I have followed the manual's instructions - I tried both [Apply] and [OK] buttons);
Did you press enter in the field to say editing is complete before you pressed ok?
It is the normal operation of the GTK UI toolkit that Geany uses that fields are changed when you press enter but actioned when you press OK. This is in compliance with the Gnome Human Interface Guidelines that GTK 3 implements. GTK has been evolving from the traditional GTK 2 desktop toolkit paradigm that allows multiple fields to be changed and actioned when "Ok" or "Apply" is clicked and the GTK 4 Gnome guidelines webby paradigm that allows individual fields to be changed and actioned and there is only a "Close" and no "Ok" or "Apply" on the dialog. Unfortunately GTK3 that Geany uses is a bit caught in the middle of that migration and has the above inconvenience.
I guess that we have differences on what the 'F' of RTFM stands for.
Compare to other IDE "manuals", even Eclipse which started out as an IBM commercial project and whose manual is huge, or Vscode which is MS backed. Neither explains basic GUI operation like text field entry (AFAICFind).
Geany is an open source project, feel free to contribute updates to the manual if you feel it is inadequate.
It's crazy, I know, but I was hoping that geany would allow customisation of things like wordchars and keywords. I
Geany is entirely dependent on what the lexers allow.
If only there was some feature like a configuration file for each file extension that allowed that.
The `filetype.xxx.conf` file you have been writing? It has the list of keywords, but its up to lexers what they test the keywords against, IIRC Perl keywords are just letters, so its not surprising that the lexer only accepts that.
The wordchars are used for things like word movements and selections, but can't be forced on lexers, which after all are for a specific language, and most languages don't have "words", they have keywords and identifiers and operators which are a fixed syntax for each language and its not surprising thats what the lexers hard code.
Thats why I keep saying the lexer is only going to be "close enough" when used for another language unless you are very lucky.
Did you press enter in the field to say editing is complete before you pressed ok?
No I didn't. That little trick fixed it. It's now as good as it will get. Thanks again for your help.
Closed #3232 as completed.
github-comments@lists.geany.org