Hummi Grammar is a subgraph description language designed for incrementally building a diagram (graph). Input is consumed from a textbox to produce either a standalone node, or a compound set of related nodes.
See Hummi Grammar Reference for a formal definition in ENBF.
Creating and linking nodes individually is tedious. A little notation greatly reduces time to add nodes and relationship to a graph.
Given a node and multiple connections, we can create the nodes and edges much faster with notation:
‘Emily likes Susan, Sally, Kim and Jim’
Commonly found in a row from a table, or survey result.
Given a node we might identify parent nodes and child nodes:
‘Hate causes Anger, and is caused by Fear’
Commonly encountered while brainstorming.
Given a set of nodes we might create them in a group:
‘Parsers, Grammars, and Chess are all good fun’
Commonly encountered while enumerating objects with a shared trait or type.
Emily;;Susan;;Sally
should be created by pressing enter instead of typing ;;
Text from the main input box populates the node contents when creating a node. Normal text can contain pretty much anything. Special operators allow several connected nodes to be created in a single statement.
Most text is the content of a node.
Some, text <b>I wrote</b>;
This text remains unchanged and be used as the content of a node. Hummi renders Markdown, HTML and Emoji. “I wrote” will render as bold.
Special double character notation indicates an operator.
>>
from <<
To create two linked nodes, enter:
P>>Q
Nodes P
and Q
are created, with a link from P
to Q
.
Whitespace on either side of an operator is ignored, but other whitespace is preserved.
Pool Party >> Q
Creates 2 nodes Pool Party
and Q
with a link from Pool Party
to Q
.
Multiple links can be created in a single statement:
Emily>>Susan>>Sally
Results in 3 nodes and 2 links. The links are from Emily
to Susan
and Emily
to Sally
.
WARNING: The link operator is not for chaining!
Hummi link operators are “relative to the head”, not “chained from head to tail”.
The example constructs Emily
linking to both Susan
and Sally
;
not a chain from Emily
to Susan
to Sally
.
Chaining is done incrementally:
>>Tom
All currently selected nodes will be connected to Tom.
When no nodes are selected, the prefix >>
creates no links.
When nodes are added, they are selected.
Entering three separate statements:
A
>>B
>>C
Produces a chain from A
to B
to C
.
First A
is created and automatically selected.
Then B
is created with a link from the selected node A
, and now B
is automatically selected.
Then C
is created with a link from the selected node B
, and now C
is automatically selected.
Explicit incremental construction without selection can be done by providing an existing name:
Sally>>Tom
Because Sally
already exists, only Tom
is created and linked from the existing Sally
.
Links can be created in both directions:
Hate>>Anger<<Fear
Results in Hate
linked to Anger
and Hate
from Fear
,
stated more simply as Fear
linked to Hate
linked to Anger
.
REMINDER: This result is a little counter-intuitive.
Visually you might have expected links to Anger
from both Hate
and Fear
.
All links are relative to the head, not chained.
Directional links can be provided in any order:
A>>B<<C>>D<<E
Results in A
linked to both B
and D
, and linked from both C
and E
.
The lack of order or grouping constructs frees you from planning ahead of time which relationships will have what direction. Instead, you add them as they occur to you. The cost is remembering that links are relative to head, and the benefit is that you can create multiple links to and from the head as they occur to you.
::
Links can be labelled like so:
P::implies>>Q
Creates P
-implies-> Q
;
2 nodes with a link between them labeled implies.
Links can also be labelled from the postfix position:
P>>Q::implies
Produces the same result P
-implies-> Q
.
So you can create a label whenever you think of it; before defining the target node, or after.
::implies
Will label any currently selected relationships. This might be useful if you thought of a label after creating a link.
[[
]]
Creating a group puts an outline around a set of nodes.
[[
indicates the desire to create a group:
[[Becky;;Ben;;Bob
Produces 3 nodes Becky
, Ben
, and Bob
in a group (outlined).
The balancing brackets is optional:
[[Becky;;Ben;;Bob]]
You can group from the right if you prefer:
Becky;;Ben;;Bob]]
All produce the same result.
Groups can contain linked nodes, and groups can link to other nodes or groups:
Becky>>Ben>>Bob]]>>Chess Club
Produces 3 nodes in a group, Becky
linked to both Ben
and Bob
,
and the surrounding group is linked to a 4th node Chess Club
.
Label groups with the ::
operator:
[[fun::Parsers;;Grammars
Or
Parsers;;Grammars::fun]]
Both create and label the group [ Parsers Grammars ]
as fun.
Hummi avoids creating duplicates except for solitary nodes and unnamed groups.
Entering [[fun:Chess
adds a node Chess
to the existing fun
group.
Entering a new relation from or to an existing name will connect with the existing name.
Entering an existing relation has no effect.
Entering 2 separate solitary node statements will create 2 nodes with the same text:
A
A
Expressions can be nested. Nested expressions tend to be ambiguous and confusing. Long statements run the risk of producing unexpected results that need significant editing. Avoid relying on nesting. Instead, grow your graph incrementally in small connected chunks.
Several tradeoffs need consideration to achieve the grammar goals.
Poorly constructed expressions will be interpreted as node text. Always accepting input is better than interrupting the user. Prefer to create one or more nodes that the user can rearrange or edit to their desired state, rather than raising an error or forcing a notational decision upon the user.
Single character operators have a higher probability for conflicting with user input.
This is addressed by using double characters (>>
<<
[[
;;
) which are almost as fast to type.
It also helps to avoid overlap with Markdown syntax, which is anticipated to be relatively common.
In the rare event that you need to use these double characters as part of the text,
the easiest thing to do is create the node without them first, and then edit it to add them.
Alternatively, operators may be escaped by an extra character: >>>
will produce a literal >>
instead of creating a link.
Would it be better to treat triples as notation?
Or preserve them?
Personal Knowledge Graphs (such as Roam) use [[
reference]]
in their markdown,
so there is potentially a notation overlap.
It seems unlikely that this overlap would affect users in any way, but it is worth considering whether another grouping operator would be preferable.
[[
has the advantage of not requiring a shift modifier to be pressed,
but ((
or {{
would also be logical choices.
Chaining is partially achievable by pressing enter.
This isn’t perfect.
Consider when entering A>>B
as one statement followed by >>C
as another statement.
Should this chain from B
to C
or should both A
and B
be linked to C
?
It is not clear that either make perfect sense, but probably both is more sensible than one because given A>>B>>C
there is no clear good single choice.
Creating unwanted links is not a huge deal as they can be deleted, but it is a little sad.
There might be a case for making >>
and <<
be chaining operators,
and provide separate relative to head operators like |>
and |<
.
This might be more intuitive, and visually pleasing without sacrificing power.
It does introduce the mental overhead of extra operators to remember.
Also, the proposed operators are not double characters, making them slower to type.
When working on a large graph sometimes it’s hard to locate a node that you know exists in the graph. Using the browser’s built-in search feature is probably not ideal. To help people locate existing nodes, it would be helpful to have a visual search feature. When typing text into the input box it might be helpful to highlight in the diagram where that text occurs. There could be an auto-completion feature so when a match is unique it will fill with that node. It might be useful to have a select operator at that point? But maybe not if the highlighting and auto-complete is sufficient.
Graphviz provides a superior file format.
It would be easy to support ->
as a synonym for >>
.
The downside is that it makes the grammar less specific.
Adding ->
should be considered if there is a desire for this from users.
Graphviz supports undirected links --
which don’t currently have meaning in Hummi.
This might be a candidate for future inclusion as bidirectional linkage or undirected linkage.
Graphviz has a property notation which is currently out of scope for Hummi Grammar.
Graphviz can be used as an import/export file format. Support for import/export of other text formats (PlantUML, Mermaid, Drakon) will be added in the future.
Groups and links can be labeled, but node labelling is currently undefined. For all intents and purposes node text is equivalent to a label. It remains to be seen if it would be useful to have node text and label be separate concepts. If they should be, then it introduces additional ambiguity into the notation. We would need to distinguish between link labels and node labels. It seems fine for the label operator to be restricted to groups and links.
It might be interesting to make
[[
Groups currently selected nodes similar to how the other operators work on selected nodes and links. But maybe users should click the Group button instead.