X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcfgparse.y;h=dbe227ddffd1b2bcce745d1c04cd8a2efc878e74;hb=fb90a556c88027b2ba639037bacb55770414a4e2;hp=bc4928f632febfb8d1ad35e7f696587ba1a8376c;hpb=77961ad9c84ade490da8d79578be764a4e77053c;p=i3%2Fi3 diff --git a/src/cfgparse.y b/src/cfgparse.y index bc4928f6..dbe227dd 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -15,6 +15,10 @@ 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); @@ -99,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; } @@ -280,19 +286,21 @@ static void start_configerror_nagbar(const char *config_path) { if (configerror_pid == 0) { char *editaction, *pageraction; - if (asprintf(&editaction, "i3-sensible-terminal -e sh -c \"i3-sensible-editor \\\"%s\\\" && i3-msg reload\"", config_path) == -1) - exit(1); - if (asprintf(&pageraction, "i3-sensible-terminal -e i3-sensible-pager \"%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 }; @@ -390,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; @@ -519,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 { @@ -553,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); @@ -642,14 +703,15 @@ void parse_file(const char *f) { %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" +%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_FONT "font" +%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" @@ -659,6 +721,7 @@ void parse_file(const char *f) { %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" @@ -683,8 +746,10 @@ void parse_file(const char *f) { %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 @@ -879,13 +944,16 @@ criterion: } ; - +qstring_or_number: + QUOTEDSTRING + | NUMBER { sasprintf(&$$, "%d", $1); } + ; word_or_number: WORD | NUMBER { - asprintf(&$$, "%d", $1); + sasprintf(&$$, "%d", $1); } ; @@ -945,6 +1013,10 @@ bar: *(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)); @@ -963,6 +1035,7 @@ barlines: barline: comment | bar_status_command + | bar_i3bar_command | bar_output | bar_tray_output | bar_position @@ -989,6 +1062,15 @@ bar_status_command: } ; +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 { @@ -1284,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 { @@ -1356,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; @@ -1369,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); @@ -1451,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 { @@ -1480,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; } ;