]> git.sur5r.net Git - i3/i3/blob - src/cmdparse.l
c333f7ae39813dc2f6376833812cb2f44dee3fcf
[i3/i3] / src / cmdparse.l
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * cmdparse.l: the lexer for commands you send to i3 (or bind on keys)
8  *
9  */
10 %option nounput
11 %option noinput
12 %option noyy_top_state
13 %option stack
14
15 %{
16 #include <stdio.h>
17 #include <string.h>
18 #include "cmdparse.tab.h"
19
20 #include "config.h"
21 #include "util.h"
22 #include "libi3.h"
23
24 int cmdyycolumn = 1;
25
26 #define YY_DECL int yylex (struct context *context)
27
28 #define YY_USER_ACTION { \
29     context->first_column = cmdyycolumn; \
30     context->last_column = cmdyycolumn+yyleng-1; \
31     cmdyycolumn += yyleng; \
32 }
33
34 /* macro to first eat whitespace, then expect a string */
35 #define WS_STRING do { \
36     yy_push_state(WANT_STRING); \
37     yy_push_state(EAT_WHITESPACE); \
38 } while (0)
39
40 %}
41
42 EOL (\r?\n)
43
44 /* handle everything up to \n as a string */
45 %s WANT_STRING
46 /* eat a whitespace, then go to the next state on the stack */
47 %s EAT_WHITESPACE
48 /* handle a quoted string or everything up to the next whitespace */
49 %s WANT_QSTRING
50
51 %x MOVE
52 %x MOVE_WS
53
54 %x EXEC
55
56 %x BUFFER_LINE
57
58 %%
59
60     {
61         /* This is called when a new line is lexed. We only want the
62          * first line to match to go into state BUFFER_LINE */
63         if (context->line_number == 0) {
64             context->line_number = 1;
65             BEGIN(INITIAL);
66             yy_push_state(BUFFER_LINE);
67         }
68     }
69
70 <BUFFER_LINE>^[^\r\n]*/{EOL}? {
71     /* save whole line */
72     context->line_copy = sstrdup(yytext);
73
74     yyless(0);
75     yy_pop_state();
76     yy_set_bol(true);
77     cmdyycolumn = 1;
78 }
79
80     /* The next/prev/back_and_forth tokens are here to recognize them *before*
81      * handling strings ('workspace' command). While flex uses the longest
82      * match, in case of a tie the order of rules becomes relevant. Since the
83      * input is fully consumed (these are the last tokens), it comes to a tie.
84      * */
85 next                            { BEGIN(INITIAL); return TOK_NEXT; }
86 prev                            { BEGIN(INITIAL); return TOK_PREV; }
87 next_on_output                  { BEGIN(INITIAL); return TOK_NEXT_ON_OUTPUT; }
88 prev_on_output                  { BEGIN(INITIAL); return TOK_PREV_ON_OUTPUT; }
89 back_and_forth                  { BEGIN(INITIAL); return TOK_BACK_AND_FORTH; }
90
91     /* MOVE is the state after a 'move' token was processed. We need this state
92      * to skip some tokens (for making the commands clearer) and to properly
93      * move to the MOVE_WS state. */
94 <MOVE>to                        { /* eat this token */ }
95 <MOVE>window                    { /* eat this token */ }
96 <MOVE>container                 { /* eat this token */ }
97 <MOVE>workspace                 { yy_pop_state(); yy_push_state(MOVE_WS); yy_push_state(EAT_WHITESPACE); return TOK_WORKSPACE; }
98 <MOVE>scratchpad                { yy_pop_state(); return TOK_SCRATCHPAD; }
99 <MOVE>up                        { yy_pop_state(); return TOK_UP; }
100 <MOVE>down                      { yy_pop_state(); return TOK_DOWN; }
101 <MOVE>left                      { yy_pop_state(); return TOK_LEFT; }
102 <MOVE>right                     { yy_pop_state(); return TOK_RIGHT; }
103
104     /* MOVE_WS is the state after a 'workspace' token was processed in the MOVE
105      * state. We need a separate state to deal with the fact that the old
106      * 'move workspace <ws>' command needs to be supported (the new command is
107      * 'move to workspace') while we also need to support
108      * 'move workspace to output <output>'. */
109 <MOVE_WS>to                     { yy_pop_state(); return TOK_TO; }
110 <MOVE_WS>[^t]                   { yy_pop_state(); yy_push_state(WANT_STRING); yyless(0); }
111
112 <WANT_STRING>\"[^\"]+\"         {
113                                   BEGIN(INITIAL);
114                                   /* strip quotes */
115                                   char *copy = sstrdup(yytext+1);
116                                   copy[strlen(copy)-1] = '\0';
117                                   cmdyylval.string = copy;
118                                   return STR;
119                                 }
120 <WANT_QSTRING>\"[^\"]+\"        {
121                                   BEGIN(INITIAL);
122                                   /* strip quotes */
123                                   char *copy = sstrdup(yytext+1);
124                                   copy[strlen(copy)-1] = '\0';
125                                   cmdyylval.string = copy;
126                                   return STR;
127                                 }
128
129 <WANT_STRING>[^;\n]+            { BEGIN(INITIAL); cmdyylval.string = sstrdup(yytext); return STR; }
130
131 <EAT_WHITESPACE>[;\n]           { BEGIN(INITIAL); return ';'; }
132 <EAT_WHITESPACE>[ \t]*          { yy_pop_state(); }
133
134 [ \t]*                          { /* ignore whitespace */ ; }
135 <EXEC>--no-startup-id           { printf("no startup id\n"); yy_pop_state(); return TOK_NO_STARTUP_ID; }
136 <EXEC>.                         { printf("anything else: *%s*\n", yytext); yyless(0); yy_pop_state(); yy_pop_state(); }
137 exec                            { WS_STRING; yy_push_state(EXEC); yy_push_state(EAT_WHITESPACE); return TOK_EXEC; }
138 exit                            { return TOK_EXIT; }
139 reload                          { return TOK_RELOAD; }
140 restart                         { return TOK_RESTART; }
141 kill                            { return TOK_KILL; }
142 window                          { return TOK_WINDOW; }
143 container                       { return TOK_CONTAINER; }
144 client                          { return TOK_CLIENT; }
145 fullscreen                      { return TOK_FULLSCREEN; }
146 global                          { return TOK_GLOBAL; }
147 layout                          { return TOK_LAYOUT; }
148 default                         { return TOK_DEFAULT; }
149 stacked                         { return TOK_STACKED; }
150 stacking                        { return TOK_STACKED; }
151 tabbed                          { return TOK_TABBED; }
152 border                          { return TOK_BORDER; }
153 normal                          { return TOK_NORMAL; }
154 none                            { return TOK_NONE; }
155 1pixel                          { return TOK_1PIXEL; }
156 mode                            { BEGIN(WANT_QSTRING); return TOK_MODE; }
157 tiling                          { return TOK_TILING; }
158 floating                        { return TOK_FLOATING; }
159 toggle                          { return TOK_TOGGLE; }
160 mode_toggle                     { return TOK_MODE_TOGGLE; }
161 workspace                       { WS_STRING; return TOK_WORKSPACE; }
162 output                          { WS_STRING; return TOK_OUTPUT; }
163 focus                           { return TOK_FOCUS; }
164 move                            { yy_push_state(MOVE); return TOK_MOVE; }
165 open                            { return TOK_OPEN; }
166 scratchpad                      { return TOK_SCRATCHPAD; }
167 show                            { return TOK_SHOW; }
168 split                           { return TOK_SPLIT; }
169 horizontal                      { return TOK_HORIZONTAL; }
170 vertical                        { return TOK_VERTICAL; }
171 up                              { return TOK_UP; }
172 down                            { return TOK_DOWN; }
173 left                            { return TOK_LEFT; }
174 right                           { return TOK_RIGHT; }
175 parent                          { return TOK_PARENT; }
176 child                           { return TOK_CHILD; }
177 resize                          { return TOK_RESIZE; }
178 shrink                          { return TOK_SHRINK; }
179 grow                            { return TOK_GROW; }
180 px                              { return TOK_PX; }
181 or                              { return TOK_OR; }
182 ppt                             { return TOK_PPT; }
183 to                              { return TOK_TO; }
184 nop                             { WS_STRING; return TOK_NOP; }
185 append_layout                   { WS_STRING; return TOK_APPEND_LAYOUT; }
186 mark                            { WS_STRING; return TOK_MARK; }
187
188 enable                          { return TOK_ENABLE; }
189 true                            { return TOK_ENABLE; }
190 yes                             { return TOK_ENABLE; }
191 disable                         { return TOK_DISABLE; }
192 false                           { return TOK_DISABLE; }
193 no                              { return TOK_DISABLE; }
194
195 class                           { BEGIN(WANT_QSTRING); return TOK_CLASS; }
196 instance                        { BEGIN(WANT_QSTRING); return TOK_INSTANCE; }
197 window_role                     { BEGIN(WANT_QSTRING); return TOK_WINDOW_ROLE; }
198 id                              { BEGIN(WANT_QSTRING); return TOK_ID; }
199 con_id                          { BEGIN(WANT_QSTRING); return TOK_CON_ID; }
200 con_mark                        { BEGIN(WANT_QSTRING); return TOK_MARK; }
201 title                           { BEGIN(WANT_QSTRING); return TOK_TITLE; }
202
203 [0-9]+                          { cmdyylval.number = atoi(yytext); return NUMBER; }
204
205 .                               { return (int)yytext[0]; }
206
207 <<EOF>> {
208     while (yy_start_stack_ptr > 0)
209         yy_pop_state();
210     yyterminate();
211 }
212
213 %%