fish completions with Raku Grammar
coding·@azarmadr3·
0.000 HBDfish completions with Raku Grammar
I have to use Perforce in my company and it has a lot of flags, subcommands as on would expect with any Version control Systems. I recently discovered fish shell (my favourite one) and started using it. This converged with me exploring Grammar concept in Raku. For two days I was writing p4 command completions for fish shell by parsing the help outputs of the commands like `p4 help` and `p4 help help`, and crafting p4 completions in a Raku script. But at the end, I discovered that there was already an official fish completions were being shipped with fish.(Since i was using the fish binary without installing it, i did not discover it earlier) ## Raku Grammar As any grammar, Raku Grammar is built upon `regex` components which can be matched against strings(generally). `regex` come in two more flavours in Raku: `token` and `rule`. For example: ```raku # resembles a line containing non `newline` char \N # with newline at the end \n my regex line { \N* \n } # resembles a paragraph consisting of multiple lines my token para { <line>+ } # resembles an essay with multiple paragraphs my rule essay { <para>+ } ``` Using the above basic components one could write Raku Grammar, which is an Object oriented class structure built into Raku. I started working on perforce help scripts on can obtain by running `p4 help` and `p4 help help`. To show a sample output: ``` Perforce client commands: add Open a new file to add it to the depot aliases Display the content of the P4ALIASES file --- --- workspaces Display list of known clients See 'p4 help administration' for more information about additional commands and issues of interest to those who are administering and operating the server. See 'p4 help dvcs' for more information about additional commands and topics of interest to those who use using Perforce with decentralized workflows. ``` For the above was the result of `p4 help help` command, which I parsed with the following Rake Grammar. ```raku grammar Cmd-Des { token TOP { <inf>+ <cd>+ <inf>+ \n { make %($/<cd>.map: { .made unless .made.key eq 'help' }) } } token cd { <id>**2 <cmd> \s+ <des> $$ { make $/<cmd>.made => $/<des>.made } } token inf { <id> <des> [\s**2 <des>]? } token des { \S+ [ \s \S+ ]* { make ~$/ } } token cmd { 'p4 help '? (\w+) { make ~$/[0] } } token id { \n* \s**4 } } ``` Grammar can be actualized with make and made concepts. Once you `make` a use of the captured strings, you can do anything with what you `made`. And that is how i made p4 fish completions. ```raku my $p4fc = open 'p4-completion.fish', :w; with Cmd-Des.parsefile('p4-help-cmds.txt').made { # `p4 help commands` .keys.sort.say; $p4fc.say: 'set -l p4_client_commands ' ~ .keys.sort.join(' ') ~ ' complete -c p4 -n "__fish_use_subcommand" -f -a help -d "Print the requested help message" complete -c p4 -n "__fish_seen_subcommand_from help" -a "$p4_client_commands" complete -c p4 -n "not __fish_contains_opt help; and __fish_seen_subcommand_from $p4_client_commands" -l explain -d "display additional information about the flags"'.indent(*); for .kv -> $c, $d { $p4fc.say: 'complete -f -c p4 -n "__fish_use_subcommand" -a ' ~ "$c -d \"$d\""; } ``` I've parsed `p4 help` and `p4 <subcommand> --explain` outputs with similar Grammar's. But at that point, I discovered the official completion file. I was stunned for a while, evaluating my choice of work over the past two days. For the past two days, all i could think of was about writing the above thing. I slept a bit late at nights (only getting 7 hrs of sleep, lol..). Even dreamt about it, though I don't have the files I've written in my dreams. Nonetheless, it was fun to code I will abandon this endeavour for now. One can find all my code at my github repo [p4-completions](https://github.com/azarmadr/p4-completions) and also check my [Replit](https://replit.com/join/kkjovqtrqi-azarmadr) invite