]> git.sur5r.net Git - i3/i3/blobdiff - docs/hacking-howto
Merge branch 'master' into next
[i3/i3] / docs / hacking-howto
index 1377d87c8c4f50086df323e7775b7d715458738b..836d5701acff304f68aa7b3e3c7ca346f9425df0 100644 (file)
@@ -63,57 +63,22 @@ to a specific file type, a window manager should not limit itself to a certain
 layout (like dwm, awesome, …) but provide mechanisms for you to easily create
 the layout you need at the moment.
 
-=== The layout table
+=== The layout tree
 
-*********************************************************************************
-This section has not been updated for v4.0 yet, sorry! We wanted to release on
-time, but we will update this soon. Please talk to us on IRC if you need to
-know stuff *NOW* :).
-*********************************************************************************
-
-/////////////////////////////////////////////////////////////////////////////////
-To accomplish flexible layouts, we decided to simply use a table. The table
-grows and shrinks as you need it. Each cell holds a container which then holds
-windows (see picture below). You can use different layouts for each container
-(default layout and stacking layout).
+The data structure which i3 uses to keep track of your windows is a tree. Every
+node in the tree is a container (type +Con+). Some containers represent actual
+windows (every container with a +window != NULL+), some represent split
+containers and a few have special purposes: they represent workspaces, outputs
+(like VGA1, LVDS1, …) or the X11 root window.
 
 So, when you open a terminal and immediately open another one, they reside in
-the same container, in default layout. The layout table has exactly one column,
-one row and therefore one cell. When you move one of the terminals to the
-right, the table needs to grow. It will be expanded to two columns and one row.
-This enables you to have different layouts for each container. The table then
-looks like this:
-
-[width="15%",cols="^,^"]
-|========
-| T1 | T2
-|========
-
-When moving terminal 2 to the bottom, the table will be expanded again.
-
-[width="15%",cols="^,^"]
-|========
-| T1 |
-|    | T2
-|========
-
-You can really think of the layout table like a traditional HTML table, if
-you’ve ever designed one. Especially col- and rowspan work similarly. Below,
-you see an example of colspan=2 for the first container (which has T1 as
-window).
-
-[width="15%",cols="^asciidoc"]
-|========
-| T1
-|
-[cols="^,^",frame="none"]
-!========
-! T2 ! T3
-!========
-|========
+the same split container, which uses the default layout. In case of an empty
+workspace, the split container we are talking about is the workspace.
 
-Furthermore, you can freely resize table cells.
-/////////////////////////////////////////////////////////////////////////////////
+To get an impression of how different layouts are represented, just play around
+and look at the data structures -- they are exposed as a JSON hash. See
+http://i3wm.org/docs/ipc.html#_get_tree_reply for documentation on that and an
+example.
 
 == Files
 
@@ -707,41 +672,123 @@ floating windows:
 
 /////////////////////////////////////////////////////////////////////////////////
 
-== User commands / commandmode (src/cmdparse.{l,y})
-
-*********************************************************************************
-This section has not been updated for v4.0 yet, sorry! We wanted to release on
-time, but we will update this soon. Please talk to us on IRC if you need to
-know stuff *NOW* :).
-*********************************************************************************
-
-/////////////////////////////////////////////////////////////////////////////////
-
-
-Like in vim, you can control i3 using commands. They are intended to be a
-powerful alternative to lots of shortcuts, because they can be combined. There
-are a few special commands, which are the following:
-
-exec <command>::
-Starts the given command by passing it to `/bin/sh`.
-
-restart::
-Restarts i3 by executing `argv[0]` (the path with which you started i3) without
-forking.
-
-w::
-"With". This is used to select a bunch of windows. Currently, only selecting
-the whole container in which the window is in, is supported by specifying "w".
-
-f, s, d::
-Toggle fullscreen, stacking, default mode for the current window/container.
-
-The other commands are to be combined with a direction. The directions are h,
-j, k and l, like in vim (h = left, j = down, k = up, l = right). When you just
-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.
-
-/////////////////////////////////////////////////////////////////////////////////
+== User commands (parser-specs/commands.spec)
+
+In the configuration file and when using i3 interactively (with +i3-msg+, for
+example), you use commands to make i3 do things, like focus a different window,
+set a window to fullscreen, and so on. An example command is +floating enable+,
+which enables floating mode for the currently focused window. See the
+appropriate section in the link:userguide.html[User’s 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
+for user commands (not yet for the configuration file).
+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()
+-----------------------------------------------------------------------
+
+The input specification is written in an extremely simple format. The
+specification is then converted into C code by the Perl script
+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.
+
+The above excerpt from commands.spec illustrates nearly all features of our
+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).
+
+=== Example: The WORKSPACE state
+
+Let’s have a look at the WORKSPACE state, which is a good example of all
+features. This is its definition:
+
+.WORKSPACE state (commands.spec)
+----------------------------------------------------------------
+# 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)
+----------------------------------------------------------------
+
+As you can see from the commands, there are multiple different valid variants
+of the workspace command:
+
+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[User’s Guide].
 
 == Moving containers