]> git.sur5r.net Git - i3/i3/commitdiff
i3bar: implement custom workspace numbers config
authorTony Crisci <tony@dubstepdish.com>
Mon, 5 May 2014 17:56:47 +0000 (13:56 -0400)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 16 May 2014 15:55:30 +0000 (17:55 +0200)
Implement the configuration option within the bar config directive for
custom workspace numbers with the directive `strip_workspace_numbers
yes`.

This directive strips the workspace name of the number prefix and
delimiter. When the workspace name consists only of the number, it will
default to show the number.

For example:

* "2:5" -> "5"
* "4:$" -> "$"
* "8" -> "8"

This allows customization of i3bar for alternate ordering of workspaces
which has a legitimate use for alternate keyboard layouts such as
Dvorak.

fixes #1131

12 files changed:
docs/userguide
i3bar/include/config.h
i3bar/include/workspaces.h
i3bar/src/config.c
i3bar/src/workspaces.c
i3bar/src/xcb.c
include/config.h
include/config_directives.h
parser-specs/config.spec
src/config_directives.c
src/ipc.c
testcases/t/201-config-parser.t

index 34f93815b4e6a53b40228e62957b6dd10daf58b1..6e5e5ff14e6d6c7ce148be04a2a6d6f2bc2bd212 100644 (file)
@@ -1191,6 +1191,31 @@ bar {
 }
 ------------------------
 
+=== Strip workspace numbers
+
+Specifies whether workspace numbers should be displayed within the workspace
+buttons. This is useful if you want to have a named workspace that stays in
+order on the bar according to its number without displaying the number prefix.
+
+When +strip_workspace_numbers+ is set to +yes+, any workspace that has a name of
+the form "[n]:[NAME]" will display only the name. You could use this, for
+instance, to display Roman numerals rather than digits by naming your
+workspaces to "1:I", "2:II", "3:III", "4:IV", ...
+
+The default is to display the full name within the workspace button.
+
+*Syntax*:
+----------------------------------
+strip_workspace_numbers <yes|no>
+----------------------------------
+
+*Example*:
+----------------------------
+bar {
+    strip_workspace_numbers yes
+}
+----------------------------
+
 === Binding Mode indicator
 
 Specifies whether the current binding mode indicator should be shown or not.
index e0b0efee1631dc91f2944159cee4246a6fca5f21..a2c16887bde80497cea14aeba6c1f7129459787c 100644 (file)
@@ -27,6 +27,7 @@ typedef struct config_t {
     struct xcb_color_strings_t colors;
     bool         disable_binding_mode_indicator;
     bool         disable_ws;
+    bool         strip_ws_numbers;
     char         *bar_id;
     char         *command;
     char         *fontname;
index 9e9ecbba817da480d2fe96afb3f42f40987786a9..d3d23c8422decde8d6e332fe15bae67533c8f384 100644 (file)
@@ -31,7 +31,8 @@ void free_workspaces(void);
 
 struct i3_ws {
     int                num;         /* The internal number of the ws */
-    i3String           *name;       /* The name of the ws */
+    char          *canonical_name;  /* The true name of the ws according to the ipc */
+    i3String           *name;       /* The name of the ws that is displayed on the bar */
     int                name_width;  /* The rendered width of the name */
     bool               visible;     /* If the ws is currently visible on an output */
     bool               focused;     /* If the ws is currently focused */
index 1390265eb0da547c371d6bca501b321445283da0..7d1c027068b61dc1532a20841fbda6c1bd5596e9 100644 (file)
@@ -193,6 +193,12 @@ static int config_boolean_cb(void *params_, int val) {
         return 1;
     }
 
+    if (!strcmp(cur_key, "strip_workspace_numbers")) {
+        DLOG("strip_workspace_numbers = %d\n", val);
+        config.strip_ws_numbers = val;
+        return 1;
+    }
+
     if (!strcmp(cur_key, "verbose")) {
         DLOG("verbose = %d\n", val);
         config.verbose = val;
index 4e6854cf7a79fab06ef80e191fdf03b615344d1a..ee2112feee0a7fcfa8087432019ccf9ca8b29ba5 100644 (file)
@@ -105,14 +105,38 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
         char *output_name;
 
         if (!strcmp(params->cur_key, "name")) {
-            /* Save the name */
-            params->workspaces_walk->name = i3string_from_utf8_with_length((const char *)val, len);
+            const char *ws_name = (const char*)val;
+            params->workspaces_walk->canonical_name = strndup(ws_name, len);
+
+            if (config.strip_ws_numbers && params->workspaces_walk->num >= 0) {
+                /* Special case: strip off the workspace number */
+                static char ws_num[10];
+
+                snprintf(ws_num, sizeof(ws_num), "%d", params->workspaces_walk->num);
+
+                /* Calculate the length of the number str in the name */
+                int offset = strspn(ws_name, ws_num);
+
+                /* Also strip off the conventional ws name delimiter */
+                if (offset && ws_name[offset] == ':')
+                    offset += 1;
+
+                /* Offset may be equal to length, in which case display the number */
+                params->workspaces_walk->name = (offset < len
+                        ? i3string_from_utf8_with_length(ws_name + offset, len - offset)
+                        : i3string_from_utf8(ws_num));
+
+            } else {
+                /* Default case: just save the name */
+                params->workspaces_walk->name = i3string_from_utf8_with_length(ws_name, len);
+            }
 
             /* Save its rendered width */
             params->workspaces_walk->name_width =
                 predict_text_width(params->workspaces_walk->name);
 
-            DLOG("Got Workspace %s, name_width: %d, glyphs: %zu\n",
+            DLOG("Got Workspace canonical: %s, name: '%s', name_width: %d, glyphs: %zu\n",
+                 params->workspaces_walk->canonical_name,
                  i3string_as_utf8(params->workspaces_walk->name),
                  params->workspaces_walk->name_width,
                  i3string_get_num_glyphs(params->workspaces_walk->name));
@@ -246,6 +270,7 @@ void free_workspaces(void) {
         if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
             TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
                 I3STRING_FREE(ws_walk->name);
+                FREE(ws_walk->canonical_name);
             }
             FREE_TAILQ(outputs_walk->workspaces, i3_ws);
         }
index 97d13ec917c98171ba3b685945ce0b860db2f064..da22066d6bc16011cb14aa73122c32826be67bdf 100644 (file)
@@ -418,7 +418,7 @@ void handle_button(xcb_button_press_event_t *event) {
      * buffer, then we copy character by character. */
     int num_quotes = 0;
     size_t namelen = 0;
-    const char *utf8_name = i3string_as_utf8(cur_ws->name);
+    const char *utf8_name = cur_ws->canonical_name;
     for (const char *walk = utf8_name; *walk != '\0'; walk++) {
         if (*walk == '"')
             num_quotes++;
index 7598241f20737156a928294e6229d28df689685f..4b951a3ad071f48b7266dde16f3c9e49cbf569bb 100644 (file)
@@ -267,6 +267,10 @@ struct Barconfig {
      * zero. */
     bool hide_workspace_buttons;
 
+    /** Strip workspace numbers? Configuration option is
+     * 'strip_workspace_numbers yes'. */
+    bool strip_workspace_numbers;
+
     /** Hide mode button? Configuration option is 'binding_mode_indicator no'
      * but we invert the bool for the same reason as hide_workspace_buttons.*/
     bool hide_binding_mode_indicator;
index a95a6473f2f8c9ad1b740e38350db1b076de9daa..5979a310bbd246b4867e6e8dc22629480c8e9035 100644 (file)
@@ -81,4 +81,5 @@ CFGFUN(bar_color_single, const char *colorclass, const char *color);
 CFGFUN(bar_status_command, const char *command);
 CFGFUN(bar_binding_mode_indicator, const char *value);
 CFGFUN(bar_workspace_buttons, const char *value);
+CFGFUN(bar_strip_workspace_numbers, const char *value);
 CFGFUN(bar_finish);
index dfd6401d4893ff9458e3a58aaf14bac64598cdd4..3899a04714d74e247bc933aa54b9a1cc3f76e048 100644 (file)
@@ -358,6 +358,7 @@ state BAR:
   'font'                   -> BAR_FONT
   'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
   'workspace_buttons'      -> BAR_WORKSPACE_BUTTONS
+  'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
   'verbose'                -> BAR_VERBOSE
   'colors'                 -> BAR_COLORS_BRACE
   '}'
@@ -420,6 +421,10 @@ state BAR_WORKSPACE_BUTTONS:
   value = word
       -> call cfg_bar_workspace_buttons($value); BAR
 
+state BAR_STRIP_WORKSPACE_NUMBERS:
+  value = word
+      -> call cfg_bar_strip_workspace_numbers($value); BAR
+
 state BAR_VERBOSE:
   value = word
       -> call cfg_bar_verbose($value); BAR
index f5a592f558ca3ae55aa1290c832c7494d4aae7b2..81f4b78bab064d15defb6afb0b72c213b0a7b614 100644 (file)
@@ -517,6 +517,10 @@ CFGFUN(bar_workspace_buttons, const char *value) {
     current_bar.hide_workspace_buttons = !eval_boolstr(value);
 }
 
+CFGFUN(bar_strip_workspace_numbers, const char *value) {
+    current_bar.strip_workspace_numbers = eval_boolstr(value);
+}
+
 CFGFUN(bar_finish) {
     DLOG("\t new bar configuration finished, saving.\n");
     /* Generate a unique ID for this bar if not already configured */
index 66c63f78f376f6df9854403ab4a74e72d0cefabe..2391518b1d2fa7dddec32867e767793858cd5913 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -514,6 +514,9 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
     ystr("workspace_buttons");
     y(bool, !config->hide_workspace_buttons);
 
+    ystr("strip_workspace_numbers");
+    y(bool, config->strip_workspace_numbers);
+
     ystr("binding_mode_indicator");
     y(bool, !config->hide_binding_mode_indicator);
 
index 55239c62d749405f0a51bc8bf1515b7c4f2be3a0..4a812c6939a1c0594ef375cc392f3d05dc4bebdf 100644 (file)
@@ -627,7 +627,7 @@ EOT
 
 $expected = <<'EOT';
 cfg_bar_output(LVDS-1)
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'verbose', 'colors', '}'
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}'
 ERROR: CONFIG: (in file <stdin>)
 ERROR: CONFIG: Line   1: bar {
 ERROR: CONFIG: Line   2:     output LVDS-1