User Tools

Site Tools


herbstlogic

===Herbstlogic=== ...doesn't exist yet! This page just serves as my notepad for syntax. I've chosen the wiki that way other users can give their input.\\ -Tylo ==Overview== Herbstlogic will be a metalanguage that can be translated into one-line 'scripts' to be passed as an argument list to herbstclient. It seeks only to provide functionality that is provided by herbstluftwm, but in a clearer and more consise syntax. Herbstlogic will be an executable that takes scripts in two ways: * Via stdin * By reading a file with a '-f' flag and prints the compiled hc arguments to stdout. Why stdin? It should allow users to script directly in their autostart, via here-documents. This has numerous advantages: * Users can substitute shell variables into their herbstlogic script. * Any changes to the herbstlogic script will be recompiled when herbstluftwm is restarted. <code=autostart> $ cat ~/.config/herbstluftwm/autostart #! /bin/bash Mod=mod4 TAG=foo herbstclient keybind $Mod-f fullscreen herbstclient keybind $Mod-a $( herbstlogic << EOF " if ( monitors.focus.index == 0 ) { emit_hook special_tag $TAG; use $TAG; } else { use_index '+1'; } " EOF '' ) $ </code> Some notes about the above example: * The value of ''$TAG'' gets substututed into the script before herbstlogic parses it, since it is in ""'s. * If the user wants to change the value of ''$TAG'', it is just like configuring anything else in autostart. * The script is only compiled when autostart is ran. The translation is loaded into memory as a keybind thereafter. * The syntax is very c-like. ''{}'' denotes a block, and '';'' is still a terminator. '';'' just expands to a chain seperator. Specification of translation as well as syntax is below. As a brief, expansion of the script is as follows. * ''if'' is a keyword expecting two arguments: if CONDITION CONSEQUENCE. Note the use of ''{}'' blocks, and ''()'' parenthesis to denote a conditional. ''if'' and it's arguments are also an atom, which returns the status of the conditional. * ''()'''s expand to conditionals, the hlwm keyword ''compare'', and additionally ''substitute compare'' if both operands of the comparision are attributes. * Since ''if'' returns the status of the conditional, ''else'' just expands to ''||'', which is later logically expanded. ==Macros== Herbstlogic just performs expansion on key words and symbols to generate the argument list. There are two types of expansion: macros and logical. Macros are the simpler expansion. Proposed keywords are as follows: * Comparisons * Comparison operators are: * ''=='' expands to ''='' * ''!='' is literal * ''<'' expands to ''lt'' * ''<='' expands to ''le'' * ''>'' expands to ''gt'' * ''>='' expands to ''ge'' * Specifying a conditional follows. * ''( ATTR COMP "LITERAL" )'' expands to ''compare my_ATTR COMP "LITERAL"'' * ''^ ( ATTR1 COMP ATTR2 )'' expands to ''substitute VAL my_ATTR2 compare my_ATTR1 COMP VAL'' Note the use of ''^'' to avoid inference of the two examples, since hlwm currently does not distinguish between attributes and literals. * Declarations. Note declarations could also add a stack element. Attributes are destroyed at the end of the current block, unless otherwise specified. Global/local namespace collision is still being considered. * Types are: * ''bool'' * ''int'' * ''string'' * ''uint'' * Declarative forms are: * ''TYPE NAME'' expands to ''new_attr TYPE my_NAME'' * ''TYPE NAME = "LITERAL"'' expands to ''new_attr TYPE my_NAME ; set_attr my_NAME "LITERAL"'' * Declarative forms can be preceded with a ''@'' to denote //global//, ie, the variable is not destroyed and removed from the stack at the end of the block. * ''='' * ''ATTR = "LITERAL"'' expands to ''set_attr my_ATTR "LITERAL"'' * ''^ ATTR1 = ATTR2'' expands to ''substitute VAL my_ATTR2 set_attr my_ATTR1 VAL'' Note the use of ''^'' to denote the special case, as to not need inference. * ''if ARG1 ARG2'' expands to ''ARG1 && { ARG2; true }'' Note that ARG1 and ARG2 can both be either conditionals or blocks, and ''if'' expands them recursively. * ''ARG1 else ARG2'' expands to ''ARG1 || ARG2''. Note that ARG1 and ARG2 can both be if statements, and ''else'' expands them recursively. For this to work, ''else'' needs greater precedence over ''if''. ==Logical Expansion== What seperates logical expansion from macros is that they need to substitue //unique seperators// for easy hlwm scope parsing. Each time a logical operator is used, a herbstlogic internal variable INDEX is changed to a unique instance. Logical keys are as follows: * ''{ ARG }'' shows scope. It is left as a literal until everything else in its parent block is expanded, then it is expanded. * ''ARG1 ; ARG2'' expands to ''chain INDEX ARG1 INDEX ARG2'' * ''ARG1 && ARG2'' expands to ''and INDEX ARG1 INDEX ARG2'' * ''ARG1 || ARG2'' expands to ''or INDEX ARG1 INDEX ARG2'' Note the redunancy: while ''{P || Q} || R'' is logically equivalent to ''P || { Q || R}'', in herbstluftwm, ''or . or .. P .. Q . R'' and ''or . P . or .. Q .. R'' is * Yes, logically equivalent. * But, no, not computationally equivalent. * Ineffiecient compared to ''or . P . Q . R'', due to parsing complexity. The parsing complexity is something that can be eleviated in the future with some inference rules, but initial precedence rules are literal expansion following the rules above.\\ The computational equivalency issue can be benchmarked later. Note, parsing left-to-right leads ''P || Q || R'' with precedence ''P || {Q || R}'', while parsing right-to-left leads it with precedence ''{P || Q} || R''.\\ Perhaps Thorsten can weigh in on which one is more equivelent since he fully understands how chain operators are parsed.\\ Note that ultimately, this issue will hopefully be elleviated with sound precedence-inference rules.

herbstlogic.txt · Last modified: 2013/03/10 19:46 by htylo