]> git.sur5r.net Git - i3/i3/blob - i3-config-wizard/cfgparse.y
Replace deprecated XKeycodeToKeysym() with XkbKeycodeToKeysym()
[i3/i3] / i3-config-wizard / cfgparse.y
1 %{
2 /*
3  * vim:ts=4:sw=4:expandtab
4  *
5  */
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <X11/Xlib.h>
16 #include <X11/XKBlib.h>
17
18 #include "libi3.h"
19
20 extern Display *dpy;
21
22 struct context {
23         int line_number;
24         char *line_copy;
25
26         char *compact_error;
27
28         /* These are the same as in YYLTYPE */
29         int first_column;
30         int last_column;
31
32         char *result;
33 };
34
35 typedef struct yy_buffer_state *YY_BUFFER_STATE;
36 extern int yylex(struct context *context);
37 extern int yyparse(void);
38 extern FILE *yyin;
39 YY_BUFFER_STATE yy_scan_string(const char *);
40
41 static struct context *context;
42
43 /* We don’t need yydebug for now, as we got decent error messages using
44  * yyerror(). Should you ever want to extend the parser, it might be handy
45  * to just comment it in again, so it stays here. */
46 //int yydebug = 1;
47
48 void yyerror(const char *error_message) {
49     fprintf(stderr, "\n");
50     fprintf(stderr, "CONFIG: %s\n", error_message);
51     fprintf(stderr, "CONFIG: line %d:\n",
52         context->line_number);
53     fprintf(stderr, "CONFIG:   %s\n", context->line_copy);
54     fprintf(stderr, "CONFIG:   ");
55     for (int c = 1; c <= context->last_column; c++)
56         if (c >= context->first_column)
57             fprintf(stderr, "^");
58         else fprintf(stderr, " ");
59     fprintf(stderr, "\n");
60     fprintf(stderr, "\n");
61 }
62
63 int yywrap() {
64     return 1;
65 }
66
67 char *rewrite_binding(const char *bindingline) {
68     char *result = NULL;
69
70     context = calloc(sizeof(struct context), 1);
71
72     yy_scan_string(bindingline);
73
74     if (yyparse() != 0) {
75         fprintf(stderr, "Could not parse configfile\n");
76         exit(1);
77     }
78
79     result = context->result;
80
81     if (context->line_copy)
82         free(context->line_copy);
83     free(context);
84
85     return result;
86 }
87
88 /* XXX: does not work for combinations of modifiers yet */
89 static char *modifier_to_string(int modifiers) {
90     //printf("should convert %d to string\n", modifiers);
91     if (modifiers == (1 << 3))
92         return strdup("$mod+");
93     else if (modifiers == ((1 << 3) | (1 << 0)))
94         return strdup("$mod+Shift+");
95     else if (modifiers == (1 << 9))
96         return strdup("$mod+");
97     else if (modifiers == ((1 << 9) | (1 << 0)))
98         return strdup("$mod+Shift+");
99     else if (modifiers == (1 << 0))
100         return strdup("Shift+");
101     else return strdup("");
102 }
103
104 %}
105
106 %error-verbose
107 %lex-param { struct context *context }
108
109 %union {
110     int number;
111     char *string;
112 }
113
114 %token <number>NUMBER "<number>"
115 %token <string>STR "<string>"
116 %token TOKBINDCODE
117 %token TOKMODVAR "$mod"
118 %token MODIFIER "<modifier>"
119 %token TOKCONTROL "control"
120 %token TOKSHIFT "shift"
121 %token WHITESPACE "<whitespace>"
122
123 %%
124
125 lines: /* empty */
126     | lines WHITESPACE bindcode
127     | lines error
128     | lines bindcode
129     ;
130
131 bindcode:
132     TOKBINDCODE WHITESPACE binding_modifiers NUMBER WHITESPACE STR
133     {
134         //printf("\tFound keycode binding mod%d with key %d and command %s\n", $<number>3, $4, $<string>6);
135         int level = 0;
136         if (($<number>3 & (1 << 0))) {
137             /* When shift is included, we really need to use the second-level
138              * symbol (upper-case). The lower-case symbol could be on a
139              * different key than the upper-case one (unlikely for letters, but
140              * more likely for special characters). */
141             level = 1;
142         }
143         KeySym sym = XkbKeycodeToKeysym(dpy, $4, 0, level);
144         char *str = XKeysymToString(sym);
145         char *modifiers = modifier_to_string($<number>3);
146         // TODO: modifier to string
147         sasprintf(&(context->result), "bindsym %s%s %s\n", modifiers, str, $<string>6);
148         free(modifiers);
149     }
150     ;
151
152 binding_modifiers:
153     /* NULL */                               { $<number>$ = 0; }
154     | binding_modifier
155     | binding_modifiers '+' binding_modifier { $<number>$ = $<number>1 | $<number>3; }
156     | binding_modifiers '+'                  { $<number>$ = $<number>1; }
157     ;
158
159 binding_modifier:
160     MODIFIER        { $<number>$ = $<number>1; }
161     | TOKMODVAR     { $<number>$ = $<number>1; }
162     | TOKCONTROL    { $<number>$ = (1 << 2); }
163     | TOKSHIFT      { $<number>$ = (1 << 0); }
164     ;