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);
*
*/
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()");
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
};
}
}
+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;
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) {
start_configerror_nagbar(f);
}
yylex_destroy();
FREE(context->line_copy);
free(context);
+ FREE(font_pattern);
free(new);
free(buf);
%token <string> WORD "<word>"
%token <string> STR "<string>"
%token <string> STR_NG "<string (non-greedy)>"
-%token <string> HEX "<hex>"
%token <string> HEXCOLOR "#<hex>"
%token <string> OUTPUT "<RandR output>"
%token TOKBINDCODE
%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_FONT "font (bar)"
%token TOK_BAR_WORKSPACE_BUTTONS "workspace_buttons"
%token TOK_BAR_VERBOSE "verbose"
%token TOK_BAR_COLORS "colors"
WORD
| NUMBER
{
- asprintf(&$$, "%d", $1);
+ sasprintf(&$$, "%d", $1);
}
;
{
printf("\t new bar configuration finished, saving.\n");
/* Generate a unique ID for this bar */
- current_bar.id = sstrdup("foo"); /* TODO */
+ 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)
+ current_bar.font = sstrdup(font_pattern);
/* Copy the current (static) structure into a dynamically allocated
* one, then cleanup our static one. */
} else {
char *ws_name = NULL;
if ($5 == NULL) {
- asprintf(&ws_name, "%d", ws_num);
+ sasprintf(&ws_name, "%d", ws_num);
} else {
ws_name = $5;
}
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;
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);
{
config.font = load_font($2, true);
printf("font %s\n", $2);
- free($2);
+ FREE(font_pattern);
+ font_pattern = $2;
}
;
;
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);
}
;