X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcfgparse.y;h=dbe227ddffd1b2bcce745d1c04cd8a2efc878e74;hb=fb90a556c88027b2ba639037bacb55770414a4e2;hp=86e9ea98ea58371f85dc3e6a00bc5f1b62f7ab76;hpb=717ae819c55d2aca9f4bf2e1198e035ca64114ac;p=i3%2Fi3 diff --git a/src/cfgparse.y b/src/cfgparse.y index 86e9ea98..dbe227dd 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -14,6 +14,11 @@ static pid_t configerror_pid = -1; static Match current_match; +static Barconfig current_bar; +/* The pattern which was specified by the user, for example -misc-fixed-*. We + * store this in a separate variable because in the i3 config struct we just + * store the i3Font. */ +static char *font_pattern; typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yylex(struct context *context); @@ -98,7 +103,9 @@ static int detect_version(char *buf) { strncasecmp(bind, "focus down", strlen("focus down")) == 0 || strncasecmp(bind, "border normal", strlen("border normal")) == 0 || strncasecmp(bind, "border 1pixel", strlen("border 1pixel")) == 0 || - strncasecmp(bind, "border borderless", strlen("border borderless")) == 0) { + strncasecmp(bind, "border borderless", strlen("border borderless")) == 0 || + strncasecmp(bind, "--no-startup-id", strlen("--no-startup-id")) == 0 || + strncasecmp(bind, "bar", strlen("bar")) == 0) { printf("deciding for version 4 due to this line: %.*s\n", (int)(walk-line), line); return 4; } @@ -240,6 +247,10 @@ static void nagbar_exited(EV_P_ ev_child *watcher, int revents) { configerror_pid = -1; } +/* We need ev >= 4 for the following code. Since it is not *that* important (it + * only makes sure that there are no i3-nagbar instances left behind) we still + * support old systems with libev 3. */ +#if EV_VERSION_MAJOR >= 4 /* * Cleanup handler. Will be called when i3 exits. Kills i3-nagbar with signal * SIGKILL (9) to make sure there are no left-over i3-nagbar processes. @@ -251,6 +262,7 @@ static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) { kill(configerror_pid, SIGKILL); } } +#endif /* * Starts an i3-nagbar process which alerts the user that his configuration @@ -260,7 +272,10 @@ static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) { * */ static void start_configerror_nagbar(const char *config_path) { - fprintf(stderr, "Would start i3-nagscreen now\n"); + if (only_check_config) + return; + + fprintf(stderr, "Starting i3-nagbar due to configuration errors\n"); configerror_pid = fork(); if (configerror_pid == -1) { warn("Could not fork()"); @@ -271,19 +286,21 @@ static void start_configerror_nagbar(const char *config_path) { if (configerror_pid == 0) { char *editaction, *pageraction; - if (asprintf(&editaction, TERM_EMU " -e sh -c \"${EDITOR:-vi} \"%s\" && i3-msg reload\"", config_path) == -1) - exit(1); - if (asprintf(&pageraction, TERM_EMU " -e sh -c \"${PAGER:-less} \"%s\"\"", errorfilename) == -1) - exit(1); + sasprintf(&editaction, "i3-sensible-terminal -e sh -c \"i3-sensible-editor \\\"%s\\\" && i3-msg reload\"", config_path); + sasprintf(&pageraction, "i3-sensible-terminal -e i3-sensible-pager \"%s\"", errorfilename); char *argv[] = { NULL, /* will be replaced by the executable path */ + "-t", + (context->has_errors ? "error" : "warning"), "-m", - "You have an error in your i3 config file!", + (context->has_errors ? + "You have an error in your i3 config file!" : + "Your config is outdated. Please fix the warnings to make sure everything works."), "-b", "edit config", editaction, (errorfilename ? "-b" : NULL), - "show errors", + (context->has_errors ? "show errors" : "show warnings"), pageraction, NULL }; @@ -296,11 +313,16 @@ static void start_configerror_nagbar(const char *config_path) { ev_child_init(child, &nagbar_exited, configerror_pid, 0); ev_child_start(main_loop, child); +/* We need ev >= 4 for the following code. Since it is not *that* important (it + * only makes sure that there are no i3-nagbar instances left behind) we still + * support old systems with libev 3. */ +#if EV_VERSION_MAJOR >= 4 /* install a cleanup watcher (will be called when i3 exits and i3-nagbar is * still running) */ ev_cleanup *cleanup = smalloc(sizeof(ev_cleanup)); ev_cleanup_init(cleanup, nagbar_cleanup); ev_cleanup_start(main_loop, cleanup); +#endif } /* @@ -376,6 +398,31 @@ static void check_for_duplicate_bindings(struct context *context) { } } +static void migrate_i3bar_exec(struct Autostart *exec) { + ELOG("**********************************************************************\n"); + ELOG("IGNORING exec command: %s\n", exec->command); + ELOG("It contains \"i3bar\". Since i3 v4.1, i3bar will be automatically started\n"); + ELOG("for each 'bar' configuration block in your i3 config. Please remove the exec\n"); + ELOG("line and add the following to your i3 config:\n"); + ELOG("\n"); + ELOG(" bar {\n"); + ELOG(" status_command i3status\n"); + ELOG(" }\n"); + ELOG("**********************************************************************\n"); + + /* Generate a dummy bar configuration */ + Barconfig *bar_config = scalloc(sizeof(Barconfig)); + /* The hard-coded ID is not a problem. It does not conflict with the + * auto-generated bar IDs and having multiple hard-coded IDs is irrelevant + * – they all just contain status_command = i3status */ + bar_config->id = sstrdup("migrate-bar"); + bar_config->status_command = sstrdup("i3status"); + TAILQ_INSERT_TAIL(&barconfigs, bar_config, configs); + + /* Trigger an i3-nagbar */ + context->has_warnings = true; +} + void parse_file(const char *f) { SLIST_HEAD(variables_head, Variable) variables = SLIST_HEAD_INITIALIZER(&variables); int fd, ret, read_bytes = 0; @@ -423,12 +470,14 @@ void parse_file(const char *f) { /* get key/value for this variable */ char *v_key = value, *v_value; - if ((v_value = strstr(value, " ")) == NULL && - (v_value = strstr(value, "\t")) == NULL) { + if (strstr(value, " ") == NULL && strstr(value, "\t") == NULL) { ELOG("Malformed variable assignment, need a value\n"); continue; } + if (!(v_value = strstr(value, " "))) + v_value = strstr(value, "\t"); + *(v_value++) = '\0'; struct Variable *new = scalloc(sizeof(struct Variable)); @@ -453,7 +502,8 @@ void parse_file(const char *f) { int extra = (strlen(current->value) - strlen(current->key)); char *next; for (next = bufcopy; - (next = strcasestr(bufcopy + (next - bufcopy), current->key)) != NULL; + next < (bufcopy + stbuf.st_size) && + (next = strcasestr(next, current->key)) != NULL; next += strlen(current->key)) { *next = '_'; extra_bytes += extra; @@ -502,15 +552,15 @@ void parse_file(const char *f) { /* We need to convert this v3 configuration */ char *converted = migrate_config(new, stbuf.st_size); if (converted != NULL) { - printf("\n"); - printf("****************************************************************\n"); - printf("NOTE: Automatically converted configuration file from v3 to v4.\n"); - printf("\n"); - printf("Please convert your config file to v4. You can use this command:\n"); - printf(" mv %s %s.O\n", f, f); - printf(" i3-migrate-config-to-v4 %s.O > %s\n", f, f); - printf("****************************************************************\n"); - printf("\n"); + ELOG("\n"); + ELOG("****************************************************************\n"); + ELOG("NOTE: Automatically converted configuration file from v3 to v4.\n"); + ELOG("\n"); + ELOG("Please convert your config file to v4. You can use this command:\n"); + ELOG(" mv %s %s.O\n", f, f); + ELOG(" i3-migrate-config-to-v4 %s.O > %s\n", f, f); + ELOG("****************************************************************\n"); + ELOG("\n"); free(new); new = converted; } else { @@ -536,13 +586,41 @@ void parse_file(const char *f) { check_for_duplicate_bindings(context); - if (context->has_errors) { + /* XXX: The following code will be removed in i3 v4.3 (three releases from + * now, as of 2011-10-22) */ + /* Check for any exec or exec_always lines starting i3bar. We remove these + * and add a bar block instead. Additionally, a i3-nagbar warning (not an + * error) will be displayed so that users update their config file. */ + struct Autostart *exec, *next; + for (exec = TAILQ_FIRST(&autostarts); exec; ) { + next = TAILQ_NEXT(exec, autostarts); + if (strstr(exec->command, "i3bar") != NULL) { + migrate_i3bar_exec(exec); + TAILQ_REMOVE(&autostarts, exec, autostarts); + } + exec = next; + } + + for (exec = TAILQ_FIRST(&autostarts_always); exec; ) { + next = TAILQ_NEXT(exec, autostarts_always); + if (strstr(exec->command, "i3bar") != NULL) { + migrate_i3bar_exec(exec); + TAILQ_REMOVE(&autostarts_always, exec, autostarts_always); + } + exec = next; + } + + if (context->has_errors || context->has_warnings) { + ELOG("FYI: You are using i3 version " I3_VERSION "\n"); + if (version == 3) + ELOG("Please convert your configfile first, then fix any remaining errors (see above).\n"); start_configerror_nagbar(f); } yylex_destroy(); FREE(context->line_copy); free(context); + FREE(font_pattern); free(new); free(buf); @@ -573,7 +651,7 @@ void parse_file(const char *f) { %token WORD "" %token STR "" %token STR_NG "" -%token HEX "" +%token HEXCOLOR "#" %token OUTPUT "" %token TOKBINDCODE %token TOKTERMINAL @@ -597,6 +675,7 @@ void parse_file(const char *f) { %token TOKCOLOR %token TOKARROW "→" %token TOKMODE "mode" +%token TOK_BAR "bar" %token TOK_ORIENTATION "default_orientation" %token TOK_HORIZ "horizontal" %token TOK_VERT "vertical" @@ -609,6 +688,8 @@ void parse_file(const char *f) { %token TOK_1PIXEL "1pixel" %token TOKFOCUSFOLLOWSMOUSE "focus_follows_mouse" %token TOK_FORCE_FOCUS_WRAPPING "force_focus_wrapping" +%token TOK_FORCE_XINERAMA "force_xinerama" +%token TOK_WORKSPACE_AUTO_BAF "workspace_auto_back_and_forth" %token TOKWORKSPACEBAR "workspace_bar" %token TOK_DEFAULT "default" %token TOK_STACKING "stacking" @@ -619,9 +700,33 @@ void parse_file(const char *f) { %token TOK_LEAVE_FULLSCREEN "leave_fullscreen" %token TOK_FOR_WINDOW "for_window" +%token TOK_BAR_OUTPUT "output (bar)" +%token TOK_BAR_TRAY_OUTPUT "tray_output" +%token TOK_BAR_SOCKET_PATH "socket_path" +%token TOK_BAR_MODE "mode (bar)" +%token TOK_BAR_HIDE "hide" +%token TOK_BAR_DOCK "dock" +%token TOK_BAR_POSITION "position" +%token TOK_BAR_BOTTOM "bottom" +%token TOK_BAR_TOP "top" +%token TOK_BAR_STATUS_COMMAND "status_command" +%token TOK_BAR_I3BAR_COMMAND "i3bar_command" +%token TOK_BAR_FONT "font (bar)" +%token TOK_BAR_WORKSPACE_BUTTONS "workspace_buttons" +%token TOK_BAR_VERBOSE "verbose" +%token TOK_BAR_COLORS "colors" +%token TOK_BAR_COLOR_BACKGROUND "background" +%token TOK_BAR_COLOR_STATUSLINE "statusline" +%token TOK_BAR_COLOR_FOCUSED_WORKSPACE "focused_workspace" +%token TOK_BAR_COLOR_ACTIVE_WORKSPACE "active_workspace" +%token TOK_BAR_COLOR_INACTIVE_WORKSPACE "inactive_workspace" +%token TOK_BAR_COLOR_URGENT_WORKSPACE "urgent_workspace" +%token TOK_NO_STARTUP_ID "--no-startup-id" + %token TOK_MARK "mark" %token TOK_CLASS "class" %token TOK_INSTANCE "instance" +%token TOK_WINDOW_ROLE "window_role" %token TOK_ID "id" %token TOK_CON_ID "con_id" %token TOK_TITLE "title" @@ -639,8 +744,12 @@ void parse_file(const char *f) { %type colorpixel %type bool %type popup_setting +%type bar_position_position +%type bar_mode_mode +%type optional_no_startup_id %type command %type word_or_number +%type qstring_or_number %type optional_workspace_name %type workspace_name %type window_class @@ -656,6 +765,7 @@ line: bindline | for_window | mode + | bar | floating_modifier | orientation | workspace_layout @@ -663,6 +773,8 @@ line: | new_float | focus_follows_mouse | force_focus_wrapping + | force_xinerama + | workspace_back_and_forth | workspace_bar | workspace | assign @@ -782,6 +894,12 @@ criterion: current_match.instance = regex_new($3); free($3); } + | TOK_WINDOW_ROLE '=' STR + { + printf("criteria: window_role = %s\n", $3); + current_match.role = regex_new($3); + free($3); + } | TOK_CON_ID '=' STR { printf("criteria: id = %s\n", $3); @@ -826,13 +944,16 @@ criterion: } ; - +qstring_or_number: + QUOTEDSTRING + | NUMBER { sasprintf(&$$, "%d", $1); } + ; word_or_number: WORD | NUMBER { - asprintf(&$$, "%d", $1); + sasprintf(&$$, "%d", $1); } ; @@ -878,6 +999,221 @@ modeline: } ; +bar: + TOK_BAR '{' barlines '}' + { + printf("\t new bar configuration finished, saving.\n"); + /* Generate a unique ID for this bar */ + current_bar.id = sstrdup("bar-XXXXXX"); + /* This works similar to mktemp in that it replaces the last six X with + * random letters, but without the restriction that the given buffer + * has to contain a valid path name. */ + char *x = current_bar.id + strlen("bar-"); + while (*x != '\0') { + *(x++) = (rand() % 26) + 'a'; + } + + /* If no font was explicitly set, we use the i3 font as default */ + if (!current_bar.font && font_pattern) + current_bar.font = sstrdup(font_pattern); + + /* Copy the current (static) structure into a dynamically allocated + * one, then cleanup our static one. */ + Barconfig *bar_config = scalloc(sizeof(Barconfig)); + memcpy(bar_config, ¤t_bar, sizeof(Barconfig)); + TAILQ_INSERT_TAIL(&barconfigs, bar_config, configs); + + memset(¤t_bar, '\0', sizeof(Barconfig)); + } + ; + +barlines: + /* empty */ + | barlines barline + ; + +barline: + comment + | bar_status_command + | bar_i3bar_command + | bar_output + | bar_tray_output + | bar_position + | bar_mode + | bar_font + | bar_workspace_buttons + | bar_verbose + | bar_socket_path + | bar_colors + | bar_color_background + | bar_color_statusline + | bar_color_focused_workspace + | bar_color_active_workspace + | bar_color_inactive_workspace + | bar_color_urgent_workspace + ; + +bar_status_command: + TOK_BAR_STATUS_COMMAND STR + { + DLOG("should add status command %s\n", $2); + FREE(current_bar.status_command); + current_bar.status_command = $2; + } + ; + +bar_i3bar_command: + TOK_BAR_I3BAR_COMMAND STR + { + DLOG("should add i3bar_command %s\n", $2); + FREE(current_bar.i3bar_command); + current_bar.i3bar_command = $2; + } + ; + +bar_output: + TOK_BAR_OUTPUT STR + { + DLOG("bar output %s\n", $2); + int new_outputs = current_bar.num_outputs + 1; + current_bar.outputs = srealloc(current_bar.outputs, sizeof(char*) * new_outputs); + current_bar.outputs[current_bar.num_outputs] = $2; + current_bar.num_outputs = new_outputs; + } + ; + +bar_tray_output: + TOK_BAR_TRAY_OUTPUT STR + { + DLOG("tray %s\n", $2); + FREE(current_bar.tray_output); + current_bar.tray_output = $2; + } + ; + +bar_position: + TOK_BAR_POSITION bar_position_position + { + DLOG("position %d\n", $2); + current_bar.position = $2; + } + ; + +bar_position_position: + TOK_BAR_TOP { $$ = P_TOP; } + | TOK_BAR_BOTTOM { $$ = P_BOTTOM; } + ; + +bar_mode: + TOK_BAR_MODE bar_mode_mode + { + DLOG("mode %d\n", $2); + current_bar.mode = $2; + } + ; + +bar_mode_mode: + TOK_BAR_HIDE { $$ = M_HIDE; } + | TOK_BAR_DOCK { $$ = M_DOCK; } + ; + +bar_font: + TOK_BAR_FONT STR + { + DLOG("font %s\n", $2); + FREE(current_bar.font); + current_bar.font = $2; + } + ; + +bar_workspace_buttons: + TOK_BAR_WORKSPACE_BUTTONS bool + { + DLOG("workspace_buttons = %d\n", $2); + /* We store this inverted to make the default setting right when + * initializing the struct with zero. */ + current_bar.hide_workspace_buttons = !($2); + } + ; + +bar_verbose: + TOK_BAR_VERBOSE bool + { + DLOG("verbose = %d\n", $2); + current_bar.verbose = $2; + } + ; + +bar_socket_path: + TOK_BAR_SOCKET_PATH STR + { + DLOG("socket_path = %s\n", $2); + FREE(current_bar.socket_path); + current_bar.socket_path = $2; + } + ; + +bar_colors: + TOK_BAR_COLORS '{' barlines '}' + { + /* At the moment, the TOK_BAR_COLORS token is only to make the config + * friendlier for humans. We might change this in the future if it gets + * more complex. */ + } + ; + +bar_color_background: + TOK_BAR_COLOR_BACKGROUND HEXCOLOR + { + DLOG("background = %s\n", $2); + current_bar.colors.background = $2; + } + ; + +bar_color_statusline: + TOK_BAR_COLOR_STATUSLINE HEXCOLOR + { + DLOG("statusline = %s\n", $2); + current_bar.colors.statusline = $2; + } + ; + +bar_color_focused_workspace: + TOK_BAR_COLOR_FOCUSED_WORKSPACE HEXCOLOR HEXCOLOR + { + DLOG("focused_ws = %s and %s\n", $2, $3); + current_bar.colors.focused_workspace_text = $2; + current_bar.colors.focused_workspace_bg = $3; + } + ; + +bar_color_active_workspace: + TOK_BAR_COLOR_ACTIVE_WORKSPACE HEXCOLOR HEXCOLOR + { + DLOG("active_ws = %s and %s\n", $2, $3); + current_bar.colors.active_workspace_text = $2; + current_bar.colors.active_workspace_bg = $3; + } + ; + +bar_color_inactive_workspace: + TOK_BAR_COLOR_INACTIVE_WORKSPACE HEXCOLOR HEXCOLOR + { + DLOG("inactive_ws = %s and %s\n", $2, $3); + current_bar.colors.inactive_workspace_text = $2; + current_bar.colors.inactive_workspace_bg = $3; + } + ; + +bar_color_urgent_workspace: + TOK_BAR_COLOR_URGENT_WORKSPACE HEXCOLOR HEXCOLOR + { + DLOG("urgent_ws = %s and %s\n", $2, $3); + current_bar.colors.urgent_workspace_text = $2; + current_bar.colors.urgent_workspace_bg = $3; + } + ; + floating_modifier: TOKFLOATING_MODIFIER binding_modifiers { @@ -1005,6 +1341,22 @@ force_focus_wrapping: } ; +force_xinerama: + TOK_FORCE_XINERAMA bool + { + DLOG("force xinerama = %d\n", $2); + config.force_xinerama = $2; + } + ; + +workspace_back_and_forth: + TOK_WORKSPACE_AUTO_BAF bool + { + DLOG("automatic workspace back-and-forth = %d\n", $2); + config.workspace_auto_back_and_forth = $2; + } + ; + workspace_bar: TOKWORKSPACEBAR bool { @@ -1014,40 +1366,39 @@ workspace_bar: ; workspace: - TOKWORKSPACE NUMBER TOKOUTPUT OUTPUT optional_workspace_name + TOKWORKSPACE qstring_or_number TOKOUTPUT OUTPUT optional_workspace_name { - int ws_num = $2; - if (ws_num < 1) { - DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); - } else { - char *ws_name = NULL; - if ($5 == NULL) { - asprintf(&ws_name, "%d", ws_num); - } else { - ws_name = $5; - } + char *ws_name = $2; + + if ($5 != NULL) { + ELOG("The old (v3) syntax workspace output is deprecated.\n"); + ELOG("Please use the new syntax: workspace \"\" output \n"); + ELOG("In your case, the following should work:\n"); + ELOG(" workspace \"%s\" output %s\n", $5, $4); + ws_name = $5; + context->has_warnings = true; + } - DLOG("Should assign workspace %s to output %s\n", ws_name, $4); - /* Check for earlier assignments of the same workspace so that we - * don’t have assignments of a single workspace to different - * outputs */ - struct Workspace_Assignment *assignment; - bool duplicate = false; - TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { - if (strcasecmp(assignment->name, ws_name) == 0) { - ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n", - ws_name); - assignment->output = $4; - duplicate = true; - } - } - if (!duplicate) { - assignment = scalloc(sizeof(struct Workspace_Assignment)); - assignment->name = ws_name; + DLOG("Assigning workspace \"%s\" to output \"%s\"\n", ws_name, $4); + /* Check for earlier assignments of the same workspace so that we + * don’t have assignments of a single workspace to different + * outputs */ + struct Workspace_Assignment *assignment; + bool duplicate = false; + TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) { + if (strcasecmp(assignment->name, ws_name) == 0) { + ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n", + ws_name); assignment->output = $4; - TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments); + duplicate = true; } } + if (!duplicate) { + assignment = scalloc(sizeof(struct Workspace_Assignment)); + assignment->name = ws_name; + assignment->output = $4; + TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments); + } } | TOKWORKSPACE NUMBER workspace_name { @@ -1086,7 +1437,7 @@ assign: ELOG("You are using the old assign syntax (without criteria). " "Please see the User's Guide for the new syntax and fix " "your config file.\n"); - context->has_errors = true; + context->has_warnings = true; printf("assignment of %s to *%s*\n", $2, $3); char *workspace = $3; char *criteria = $2; @@ -1099,20 +1450,14 @@ assign: if ((separator = strchr(criteria, '/')) != NULL) { *(separator++) = '\0'; char *pattern; - if (asprintf(&pattern, "(?i)%s", separator) == -1) { - ELOG("asprintf failed\n"); - break; - } + sasprintf(&pattern, "(?i)%s", separator); match->title = regex_new(pattern); free(pattern); printf(" title = %s\n", separator); } if (*criteria != '\0') { char *pattern; - if (asprintf(&pattern, "(?i)%s", criteria) == -1) { - ELOG("asprintf failed\n"); - break; - } + sasprintf(&pattern, "(?i)%s", criteria); match->class = regex_new(pattern); free(pattern); printf(" class = %s\n", criteria); @@ -1148,6 +1493,10 @@ assign: } | TOKASSIGN match STR { + if (match_is_empty(¤t_match)) { + ELOG("Match is empty, ignoring this assignment\n"); + break; + } printf("new assignment, using above criteria, to workspace %s\n", $3); Assignment *assignment = scalloc(sizeof(Assignment)); assignment->match = current_match; @@ -1177,23 +1526,30 @@ restart_state: ; exec: - TOKEXEC STR + TOKEXEC optional_no_startup_id STR { struct Autostart *new = smalloc(sizeof(struct Autostart)); - new->command = $2; + new->command = $3; + new->no_startup_id = $2; TAILQ_INSERT_TAIL(&autostarts, new, autostarts); } ; exec_always: - TOKEXEC_ALWAYS STR + TOKEXEC_ALWAYS optional_no_startup_id STR { struct Autostart *new = smalloc(sizeof(struct Autostart)); - new->command = $2; + new->command = $3; + new->no_startup_id = $2; TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always); } ; +optional_no_startup_id: + /* empty */ { $$ = false; } + | TOK_NO_STARTUP_ID { $$ = true; } + ; + terminal: TOKTERMINAL STR { @@ -1206,8 +1562,10 @@ font: TOKFONT STR { config.font = load_font($2, true); + set_font(&config.font); printf("font %s\n", $2); - free($2); + FREE(font_pattern); + font_pattern = $2; } ; @@ -1231,14 +1589,10 @@ color: ; colorpixel: - '#' HEX + HEXCOLOR { - char *hex; - if (asprintf(&hex, "#%s", $2) == -1) - die("asprintf()"); - free($2); - $$ = get_colorpixel(hex); - free(hex); + $$ = get_colorpixel($1); + free($1); } ;