hacking-howto: describe the new commands parser

This commit is contained in:
Michael Stapelberg 2012-01-16 22:44:28 +00:00
parent a59090ac2e
commit fa4a909f34
1 changed files with 106 additions and 25 deletions

View File

@ -672,41 +672,122 @@ floating windows:
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
== User commands / commandmode (src/cmdparse.{l,y}) == User commands (parser-specs/commands.spec)
********************************************************************************* In the configuration file and when using i3 interactively (with +i3-msg+, for
This section has not been updated for v4.0 yet, sorry! We wanted to release on example), you use commands to make i3 do things, like focus a different window,
time, but we will update this soon. Please talk to us on IRC if you need to set a window to fullscreen, and so on. An example command is +floating enable+,
know stuff *NOW* :). which enables floating mode for the currently focused window. See the
********************************************************************************* appropriate section in the link:userguide.html[Users Guide] for a reference of
all commands.
///////////////////////////////////////////////////////////////////////////////// In earlier versions of i3, interpreting these commands was done using lex and
yacc, but experience has shown that lex and yacc are not well suited for our
command language. Therefore, starting from version 4.2, we use a custom parser.
The input specification for this parser can be found in the file
+parser-specs/commands.spec+. Should you happen to use Vim as an editor, use
:source parser-specs/highlighting.vim to get syntax highlighting for this file
(highlighting files for other editors are welcome).
.Excerpt from commands.spec
-----------------------------------------------------------------------
state INITIAL:
'[' -> call cmd_criteria_init(); CRITERIA
'move' -> MOVE
'exec' -> EXEC
'workspace' -> WORKSPACE
'exit' -> call cmd_exit()
'restart' -> call cmd_restart()
'reload' -> call cmd_reload()
-----------------------------------------------------------------------
Like in vim, you can control i3 using commands. They are intended to be a The input specification is written in an extremely simple format. The
powerful alternative to lots of shortcuts, because they can be combined. There specification is then converted into C code by the Perl script
are a few special commands, which are the following: generate-commands-parser.pl (the output file names begin with GENERATED and the
files are stored in the +include+ directory). The parser implementation
+src/commands_parser.c+ includes the generated C code at compile-time.
exec <command>:: The above excerpt from commands.spec illustrates nearly all features of our
Starts the given command by passing it to `/bin/sh`. specification format: You describe different states and what can happen within
each state. State names are all-caps; the state in the above excerpt is called
INITIAL. A list of tokens and their actions (separated by an ASCII arrow)
follows. In the excerpt, all tokens are literals, that is, simple text strings
which will be compared with the input. An action is either the name of a state
in which the parser will transition into, or the keyword 'call', followed by
the name of a function (and optionally a state).
restart:: === Example: The WORKSPACE state
Restarts i3 by executing `argv[0]` (the path with which you started i3) without
forking.
w:: Lets have a look at the WORKSPACE state, which is a good example of all
"With". This is used to select a bunch of windows. Currently, only selecting features. This is its definition:
the whole container in which the window is in, is supported by specifying "w".
f, s, d:: .WORKSPACE state (commands.spec)
Toggle fullscreen, stacking, default mode for the current window/container. ----------------------------------------------------------------
# workspace next|prev|next_on_output|prev_on_output
# workspace back_and_forth
# workspace <name>
state WORKSPACE:
direction = 'next_on_output', 'prev_on_output', 'next', 'prev'
-> call cmd_workspace($direction)
'back_and_forth'
-> call cmd_workspace_back_and_forth()
workspace = string
-> call cmd_workspace_name($workspace)
----------------------------------------------------------------
The other commands are to be combined with a direction. The directions are h, As you can see from the commands, there are multiple different valid variants
j, k and l, like in vim (h = left, j = down, k = up, l = right). When you just of the workspace command:
specify the direction keys, i3 will move the focus in that direction. You can
provide "m" or "s" before the direction to move a window respectively or snap.
///////////////////////////////////////////////////////////////////////////////// workspace <direction>::
The word 'workspace' can be followed by any of the tokens 'next',
'prev', 'next_on_output' or 'prev_on_output'. This command will
switch to the next or previous workspace (optionally on the same
output). +
There is one function called +cmd_workspace+, which is defined
in +src/commands.c+. It will handle this kind of command. To know which
direction was specified, the direction token is stored on the stack
with the name "direction", which is what the "direction = " means in
the beginning. +
NOTE: Note that you can specify multiple literals in the same line. This has
exactly the same effect as if you specified `direction =
'next_on_output' -> call cmd_workspace($direction)` and so forth. +
NOTE: Also note that the order of literals is important here: If 'next' were
ordered before 'next_on_output', then 'next_on_output' would never
match.
workspace back_and_forth::
This is a very simple case: When the literal 'back_and_forth' is found
in the input, the function +cmd_workspace_back_and_forth+ will be
called without parameters and the parser will return to the INITIAL
state (since no other state was specified).
workspace <name>::
In this case, the workspace command is followed by an arbitrary string,
possibly in quotes, for example "workspace 3" or "workspace bleh". +
This is the first time that the token is actually not a literal (not in
single quotes), but just called string. Other possible tokens are word
(the same as string, but stops matching at a whitespace) and end
(matches the end of the input).
=== Introducing a new command
The following steps have to be taken in order to properly introduce a new
command (or possibly extend an existing command):
1. Define a function beginning with +cmd_+ in the file +src/commands.c+. Copy
the prototype of an existing function.
2. After adding a comment on what the function does, copy the comment and
function definition to +include/commands.h+. Make the comment in the header
file use double asterisks to make doxygen pick it up.
3. Write a test case (or extend an existing test case) for your feature, see
link:testsuite.html[i3 testsuite]. For now, it is sufficient to simply call
your command in all the various possible ways.
4. Extend the parser specification in +parser-specs/commands.spec+. Run the
testsuite and see if your new function gets called with the appropriate
arguments for the appropriate input.
5. Actually implement the feature.
6. Document the feature in the link:userguide.html[Users Guide].
== Moving containers == Moving containers