]> git.sur5r.net Git - i3/i3/blobdiff - src/cfgparse.y
Introduce a new syntax for the 'assign' command:
[i3/i3] / src / cfgparse.y
index 8426de0b3dd7b9b7633e9cde6c31eb43d7251698..53d23815caf9145ac431fccf076ee6920449bf23 100644 (file)
@@ -188,6 +188,7 @@ static char *migrate_config(char *input, off_t size) {
         ret = read(readpipe[0], converted + read_bytes, conv_size - read_bytes);
         if (ret == -1) {
             warn("Cannot read from pipe");
+            FREE(converted);
             return NULL;
         }
         read_bytes += ret;
@@ -239,6 +240,18 @@ static void nagbar_exited(EV_P_ ev_child *watcher, int revents) {
     configerror_pid = -1;
 }
 
+/*
+ * 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.
+ *
+ */
+static void nagbar_cleanup(EV_P_ ev_cleanup *watcher, int revent) {
+    if (configerror_pid != -1) {
+        LOG("Sending SIGKILL (9) to i3-nagbar with PID %d\n", configerror_pid);
+        kill(configerror_pid, SIGKILL);
+    }
+}
+
 /*
  * Starts an i3-nagbar process which alerts the user that his configuration
  * file contains one or more errors. Also offers two buttons: One to launch an
@@ -282,6 +295,12 @@ static void start_configerror_nagbar(const char *config_path) {
     ev_child *child = smalloc(sizeof(ev_child));
     ev_child_init(child, &nagbar_exited, configerror_pid, 0);
     ev_child_start(main_loop, child);
+
+    /* 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);
 }
 
 /*
@@ -397,13 +416,18 @@ void parse_file(const char *f) {
             continue;
 
         if (strcasecmp(key, "set") == 0) {
-            if (value[0] != '$')
-                die("Malformed variable assignment, name has to start with $\n");
+            if (value[0] != '$') {
+                ELOG("Malformed variable assignment, name has to start with $\n");
+                continue;
+            }
 
             /* get key/value for this variable */
             char *v_key = value, *v_value;
-            if ((v_value = strstr(value, " ")) == NULL)
-                die("Malformed variable assignment, need a value\n");
+            if ((v_value = strstr(value, " ")) == NULL &&
+                (v_value = strstr(value, "\t")) == NULL) {
+                ELOG("Malformed variable assignment, need a value\n");
+                continue;
+            }
 
             *(v_value++) = '\0';
 
@@ -579,6 +603,7 @@ void parse_file(const char *f) {
 %token                  TOK_AUTO                    "auto"
 %token                  TOK_WORKSPACE_LAYOUT        "workspace_layout"
 %token                  TOKNEWWINDOW                "new_window"
+%token                  TOKNEWFLOAT                 "new_float"
 %token                  TOK_NORMAL                  "normal"
 %token                  TOK_NONE                    "none"
 %token                  TOK_1PIXEL                  "1pixel"
@@ -610,6 +635,7 @@ void parse_file(const char *f) {
 %type   <number>        layout_mode
 %type   <number>        border_style
 %type   <number>        new_window
+%type   <number>        new_float
 %type   <number>        colorpixel
 %type   <number>        bool
 %type   <number>        popup_setting
@@ -634,6 +660,7 @@ line:
     | orientation
     | workspace_layout
     | new_window
+    | new_float
     | focus_follows_mouse
     | force_focus_wrapping
     | workspace_bar
@@ -742,12 +769,14 @@ criterion:
     TOK_CLASS '=' STR
     {
         printf("criteria: class = %s\n", $3);
-        current_match.class = $3;
+        current_match.class = regex_new($3);
+        free($3);
     }
     | TOK_INSTANCE '=' STR
     {
         printf("criteria: instance = %s\n", $3);
-        current_match.instance = $3;
+        current_match.instance = regex_new($3);
+        free($3);
     }
     | TOK_CON_ID '=' STR
     {
@@ -782,12 +811,14 @@ criterion:
     | TOK_MARK '=' STR
     {
         printf("criteria: mark = %s\n", $3);
-        current_match.mark = $3;
+        current_match.mark = regex_new($3);
+        free($3);
     }
     | TOK_TITLE '=' STR
     {
         printf("criteria: title = %s\n", $3);
-        current_match.title = $3;
+        current_match.title = regex_new($3);
+        free($3);
     }
     ;
 
@@ -924,6 +955,14 @@ new_window:
     }
     ;
 
+new_float:
+    TOKNEWFLOAT border_style
+    {
+       DLOG("new floating windows should start with border style %d\n", $2);
+       config.default_floating_border = $2;
+    }
+    ;
+
 border_style:
     TOK_NORMAL      { $$ = BS_NORMAL; }
     | TOK_NONE      { $$ = BS_NONE; }
@@ -985,10 +1024,25 @@ workspace:
             }
 
             DLOG("Should assign workspace %s to output %s\n", ws_name, $4);
-            struct Workspace_Assignment *assignment = scalloc(sizeof(struct Workspace_Assignment));
-            assignment->name = ws_name;
-            assignment->output = $4;
-            TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
+            /* 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;
+                assignment->output = $4;
+                TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
+            }
         }
     }
     | TOKWORKSPACE NUMBER workspace_name
@@ -1022,6 +1076,8 @@ workspace_name:
 assign:
     TOKASSIGN window_class STR
     {
+        /* TODO: the assign command also needs some kind of new syntax where we
+         * just use criteria. Then deprecate the old form */
         printf("assignment of %s to *%s*\n", $2, $3);
         char *workspace = $3;
         char *criteria = $2;
@@ -1033,15 +1089,27 @@ assign:
         char *separator = NULL;
         if ((separator = strchr(criteria, '/')) != NULL) {
             *(separator++) = '\0';
-            match->title = sstrdup(separator);
+            char *pattern;
+            if (asprintf(&pattern, "(?i)%s", separator) == -1) {
+                ELOG("asprintf failed\n");
+                break;
+            }
+            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;
+            }
+            match->class = regex_new(pattern);
+            free(pattern);
+            printf("  class = %s\n", criteria);
         }
-        if (*criteria != '\0')
-            match->class = sstrdup(criteria);
         free(criteria);
 
-        printf("  class = %s\n", match->class);
-        printf("  title = %s\n", match->title);
-
         /* Compatibility with older versions: If the assignment target starts
          * with ~, we create the equivalent of:
          *
@@ -1069,6 +1137,15 @@ assign:
         assignment->dest.workspace = workspace;
         TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
     }
+    | TOKASSIGN match STR
+    {
+        printf("new assignment, using above criteria, to workspace %s\n", $3);
+        Assignment *assignment = scalloc(sizeof(Assignment));
+        assignment->match = current_match;
+        assignment->type = A_TO_WORKSPACE;
+        assignment->dest.workspace = $3;
+        TAILQ_INSERT_TAIL(&assignments, assignment, assignments);
+    }
     ;
 
 window_class:
@@ -1150,6 +1227,7 @@ colorpixel:
         char *hex;
         if (asprintf(&hex, "#%s", $2) == -1)
             die("asprintf()");
+        free($2);
         $$ = get_colorpixel(hex);
         free(hex);
     }