a532f5ac39
On the rationale of using a custom parser instead of a lex/yacc one, see this quote from src/commands_parser.c: We use a hand-written parser instead of lex/yacc because our commands are easy for humans, not for computers. Thus, it’s quite hard to specify a context-free grammar for the commands. A PEG grammar would be easier, but there’s downsides to every PEG parser generator I have come accross so far. This parser is basically a state machine which looks for literals or strings and can push either on a stack. After identifying a literal or string, it will either transition to the current state, to a different state, or call a function (like cmd_move()). Special care has been taken that error messages are useful and the code is well testable (when compiled with -DTEST_PARSER it will output to stdout instead of actually calling any function). During the migration phase (I plan to completely switch to this parser before 4.2 will be released), the new parser will parse every command you send to i3 and save the resulting call stack. Then, the old parser will parse your input and actually execute the commands. Afterwards, both call stacks will be compared and any differences will be logged. The new parser works with 100% of the test suite and produces identical call stacks.
234 lines
5.4 KiB
Ruby
234 lines
5.4 KiB
Ruby
# vim:ts=2:sw=2:expandtab
|
|
#
|
|
# i3 - an improved dynamic tiling window manager
|
|
# © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
|
|
#
|
|
# parser-specs/commands.spec: Specification file for generate-command-parser.pl
|
|
# which will generate the appropriate header files for our C parser.
|
|
#
|
|
# Use :source highlighting.vim in vim to get syntax highlighting
|
|
# for this file.
|
|
|
|
state INITIAL:
|
|
# We have an end token here for all the commands which just call some
|
|
# function without using an explicit 'end' token.
|
|
end ->
|
|
'[' -> call cmd_criteria_init(); CRITERIA
|
|
'move' -> MOVE
|
|
'exec' -> EXEC
|
|
'exit' -> call cmd_exit()
|
|
'restart' -> call cmd_restart()
|
|
'reload' -> call cmd_reload()
|
|
'border' -> BORDER
|
|
'layout' -> LAYOUT
|
|
'append_layout' -> APPEND_LAYOUT
|
|
'workspace' -> WORKSPACE
|
|
'focus' -> FOCUS
|
|
'kill' -> KILL
|
|
'open' -> call cmd_open()
|
|
'fullscreen' -> FULLSCREEN
|
|
'split' -> SPLIT
|
|
'floating' -> FLOATING
|
|
'mark' -> MARK
|
|
'resize' -> RESIZE
|
|
'nop' -> NOP
|
|
'scratchpad' -> SCRATCHPAD
|
|
'mode' -> MODE
|
|
|
|
state CRITERIA:
|
|
ctype = 'class' -> CRITERION
|
|
ctype = 'instance' -> CRITERION
|
|
ctype = 'window_role' -> CRITERION
|
|
ctype = 'con_id' -> CRITERION
|
|
ctype = 'id' -> CRITERION
|
|
ctype = 'con_mark' -> CRITERION
|
|
ctype = 'title' -> CRITERION
|
|
']' -> call cmd_criteria_match_windows(); INITIAL
|
|
|
|
state CRITERION:
|
|
'=' -> CRITERION_STR
|
|
|
|
state CRITERION_STR:
|
|
cvalue = word
|
|
-> call cmd_criteria_add($ctype, $cvalue); CRITERIA
|
|
|
|
# exec [--no-startup-id] <command>
|
|
state EXEC:
|
|
nosn = '--no-startup-id'
|
|
->
|
|
command = string
|
|
-> call cmd_exec($nosn, $command)
|
|
|
|
# border <normal|none|1pixel|toggle>
|
|
state BORDER:
|
|
border_style = 'normal', 'none', '1pixel', 'toggle'
|
|
-> call cmd_border($border_style)
|
|
|
|
# layout <default|stacked|stacking|tabbed>
|
|
state LAYOUT:
|
|
layout_mode = 'default', 'stacked', 'stacking', 'tabbed'
|
|
-> call cmd_layout($layout_mode)
|
|
|
|
# append_layout <path>
|
|
state APPEND_LAYOUT:
|
|
path = string -> call cmd_append_layout($path)
|
|
|
|
# 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)
|
|
|
|
# focus left|right|up|down
|
|
# focus output <output>
|
|
# focus tiling|floating|mode_toggle
|
|
# focus parent|child
|
|
# focus
|
|
state FOCUS:
|
|
direction = 'left', 'right', 'up', 'down'
|
|
-> call cmd_focus_direction($direction)
|
|
'output'
|
|
-> FOCUS_OUTPUT
|
|
window_mode = 'tiling', 'floating', 'mode_toggle'
|
|
-> call cmd_focus_window_mode($window_mode)
|
|
level = 'parent', 'child'
|
|
-> call cmd_focus_level($level)
|
|
end
|
|
-> call cmd_focus()
|
|
|
|
state FOCUS_OUTPUT:
|
|
output = string
|
|
-> call cmd_focus_output($output)
|
|
|
|
# kill window|client
|
|
# kill
|
|
state KILL:
|
|
kill_mode = 'window', 'client'
|
|
-> call cmd_kill($kill_mode)
|
|
end
|
|
-> call cmd_kill($kill_mode)
|
|
|
|
# fullscreen global
|
|
# fullscreen
|
|
state FULLSCREEN:
|
|
fullscreen_mode = 'global'
|
|
-> call cmd_fullscreen($fullscreen_mode)
|
|
end
|
|
-> call cmd_fullscreen($fullscreen_mode)
|
|
|
|
# split v|h|vertical|horizontal
|
|
state SPLIT:
|
|
direction = 'v', 'h', 'vertical', 'horizontal'
|
|
-> call cmd_split($direction)
|
|
|
|
# floating enable|disable|toggle
|
|
state FLOATING:
|
|
floating = 'enable', 'disable', 'toggle'
|
|
-> call cmd_floating($floating)
|
|
|
|
# mark <mark>
|
|
state MARK:
|
|
mark = string
|
|
-> call cmd_mark($mark)
|
|
|
|
# resize
|
|
state RESIZE:
|
|
way = 'grow', 'shrink'
|
|
-> RESIZE_DIRECTION
|
|
|
|
state RESIZE_DIRECTION:
|
|
direction = 'up', 'down', 'left', 'right'
|
|
-> RESIZE_PX
|
|
|
|
state RESIZE_PX:
|
|
resize_px = word
|
|
-> RESIZE_TILING
|
|
end
|
|
-> call cmd_resize($way, $direction, "10", "10")
|
|
|
|
state RESIZE_TILING:
|
|
'px'
|
|
->
|
|
'or'
|
|
-> RESIZE_TILING_OR
|
|
end
|
|
-> call cmd_resize($way, $direction, $resize_px, "10")
|
|
|
|
state RESIZE_TILING_OR:
|
|
'ppt'
|
|
->
|
|
resize_ppt = word
|
|
->
|
|
end
|
|
-> call cmd_resize($way, $direction, $resize_px, $resize_ppt)
|
|
|
|
# move <direction> [<pixels> [px]]
|
|
# move [window|container] [to] workspace <str>
|
|
# move [window|container] [to] output <str>
|
|
# move [window|container] [to] scratchpad
|
|
# move workspace to [output] <str>
|
|
# move scratchpad
|
|
state MOVE:
|
|
'window'
|
|
->
|
|
'container'
|
|
->
|
|
'to'
|
|
->
|
|
'workspace'
|
|
-> MOVE_WORKSPACE
|
|
'output'
|
|
-> MOVE_TO_OUTPUT
|
|
'scratchpad'
|
|
-> call cmd_move_scratchpad()
|
|
direction = 'left', 'right', 'up', 'down'
|
|
-> MOVE_DIRECTION
|
|
|
|
state MOVE_DIRECTION:
|
|
pixels = word
|
|
-> MOVE_DIRECTION_PX
|
|
end
|
|
-> call cmd_move_direction($direction, "10")
|
|
|
|
state MOVE_DIRECTION_PX:
|
|
'px'
|
|
-> call cmd_move_direction($direction, $pixels)
|
|
end
|
|
-> call cmd_move_direction($direction, $pixels)
|
|
|
|
state MOVE_WORKSPACE:
|
|
'to'
|
|
-> MOVE_WORKSPACE_TO_OUTPUT
|
|
workspace = 'next', 'prev', 'next_on_output', 'prev_on_output'
|
|
-> call cmd_move_con_to_workspace($workspace)
|
|
workspace = string
|
|
-> call cmd_move_con_to_workspace_name($workspace)
|
|
|
|
state MOVE_TO_OUTPUT:
|
|
output = string
|
|
-> call cmd_move_con_to_output($output)
|
|
|
|
state MOVE_WORKSPACE_TO_OUTPUT:
|
|
'output'
|
|
->
|
|
output = string
|
|
-> call cmd_move_workspace_to_output($output)
|
|
|
|
# mode <string>
|
|
state MODE:
|
|
mode = string
|
|
-> call cmd_mode($mode)
|
|
|
|
state NOP:
|
|
comment = string
|
|
-> call cmd_nop($comment)
|
|
|
|
state SCRATCHPAD:
|
|
'show'
|
|
-> call cmd_scratchpad_show()
|