i3bar: implement custom workspace numbers config
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
This commit is contained in:
parent
e2f47ef466
commit
e707e0a5fa
|
@ -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
|
=== Binding Mode indicator
|
||||||
|
|
||||||
Specifies whether the current binding mode indicator should be shown or not.
|
Specifies whether the current binding mode indicator should be shown or not.
|
||||||
|
|
|
@ -27,6 +27,7 @@ typedef struct config_t {
|
||||||
struct xcb_color_strings_t colors;
|
struct xcb_color_strings_t colors;
|
||||||
bool disable_binding_mode_indicator;
|
bool disable_binding_mode_indicator;
|
||||||
bool disable_ws;
|
bool disable_ws;
|
||||||
|
bool strip_ws_numbers;
|
||||||
char *bar_id;
|
char *bar_id;
|
||||||
char *command;
|
char *command;
|
||||||
char *fontname;
|
char *fontname;
|
||||||
|
|
|
@ -31,7 +31,8 @@ void free_workspaces(void);
|
||||||
|
|
||||||
struct i3_ws {
|
struct i3_ws {
|
||||||
int num; /* The internal number of the 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 */
|
int name_width; /* The rendered width of the name */
|
||||||
bool visible; /* If the ws is currently visible on an output */
|
bool visible; /* If the ws is currently visible on an output */
|
||||||
bool focused; /* If the ws is currently focused */
|
bool focused; /* If the ws is currently focused */
|
||||||
|
|
|
@ -193,6 +193,12 @@ static int config_boolean_cb(void *params_, int val) {
|
||||||
return 1;
|
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")) {
|
if (!strcmp(cur_key, "verbose")) {
|
||||||
DLOG("verbose = %d\n", val);
|
DLOG("verbose = %d\n", val);
|
||||||
config.verbose = val;
|
config.verbose = val;
|
||||||
|
|
|
@ -105,14 +105,38 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, size_t
|
||||||
char *output_name;
|
char *output_name;
|
||||||
|
|
||||||
if (!strcmp(params->cur_key, "name")) {
|
if (!strcmp(params->cur_key, "name")) {
|
||||||
/* Save the name */
|
const char *ws_name = (const char*)val;
|
||||||
params->workspaces_walk->name = i3string_from_utf8_with_length((const char *)val, len);
|
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 */
|
/* Save its rendered width */
|
||||||
params->workspaces_walk->name_width =
|
params->workspaces_walk->name_width =
|
||||||
predict_text_width(params->workspaces_walk->name);
|
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),
|
i3string_as_utf8(params->workspaces_walk->name),
|
||||||
params->workspaces_walk->name_width,
|
params->workspaces_walk->name_width,
|
||||||
i3string_get_num_glyphs(params->workspaces_walk->name));
|
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)) {
|
if (outputs_walk->workspaces != NULL && !TAILQ_EMPTY(outputs_walk->workspaces)) {
|
||||||
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
|
||||||
I3STRING_FREE(ws_walk->name);
|
I3STRING_FREE(ws_walk->name);
|
||||||
|
FREE(ws_walk->canonical_name);
|
||||||
}
|
}
|
||||||
FREE_TAILQ(outputs_walk->workspaces, i3_ws);
|
FREE_TAILQ(outputs_walk->workspaces, i3_ws);
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,7 +418,7 @@ void handle_button(xcb_button_press_event_t *event) {
|
||||||
* buffer, then we copy character by character. */
|
* buffer, then we copy character by character. */
|
||||||
int num_quotes = 0;
|
int num_quotes = 0;
|
||||||
size_t namelen = 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++) {
|
for (const char *walk = utf8_name; *walk != '\0'; walk++) {
|
||||||
if (*walk == '"')
|
if (*walk == '"')
|
||||||
num_quotes++;
|
num_quotes++;
|
||||||
|
|
|
@ -267,6 +267,10 @@ struct Barconfig {
|
||||||
* zero. */
|
* zero. */
|
||||||
bool hide_workspace_buttons;
|
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'
|
/** Hide mode button? Configuration option is 'binding_mode_indicator no'
|
||||||
* but we invert the bool for the same reason as hide_workspace_buttons.*/
|
* but we invert the bool for the same reason as hide_workspace_buttons.*/
|
||||||
bool hide_binding_mode_indicator;
|
bool hide_binding_mode_indicator;
|
||||||
|
|
|
@ -81,4 +81,5 @@ CFGFUN(bar_color_single, const char *colorclass, const char *color);
|
||||||
CFGFUN(bar_status_command, const char *command);
|
CFGFUN(bar_status_command, const char *command);
|
||||||
CFGFUN(bar_binding_mode_indicator, const char *value);
|
CFGFUN(bar_binding_mode_indicator, const char *value);
|
||||||
CFGFUN(bar_workspace_buttons, const char *value);
|
CFGFUN(bar_workspace_buttons, const char *value);
|
||||||
|
CFGFUN(bar_strip_workspace_numbers, const char *value);
|
||||||
CFGFUN(bar_finish);
|
CFGFUN(bar_finish);
|
||||||
|
|
|
@ -358,6 +358,7 @@ state BAR:
|
||||||
'font' -> BAR_FONT
|
'font' -> BAR_FONT
|
||||||
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
||||||
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
||||||
|
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
||||||
'verbose' -> BAR_VERBOSE
|
'verbose' -> BAR_VERBOSE
|
||||||
'colors' -> BAR_COLORS_BRACE
|
'colors' -> BAR_COLORS_BRACE
|
||||||
'}'
|
'}'
|
||||||
|
@ -420,6 +421,10 @@ state BAR_WORKSPACE_BUTTONS:
|
||||||
value = word
|
value = word
|
||||||
-> call cfg_bar_workspace_buttons($value); BAR
|
-> 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:
|
state BAR_VERBOSE:
|
||||||
value = word
|
value = word
|
||||||
-> call cfg_bar_verbose($value); BAR
|
-> call cfg_bar_verbose($value); BAR
|
||||||
|
|
|
@ -517,6 +517,10 @@ CFGFUN(bar_workspace_buttons, const char *value) {
|
||||||
current_bar.hide_workspace_buttons = !eval_boolstr(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) {
|
CFGFUN(bar_finish) {
|
||||||
DLOG("\t new bar configuration finished, saving.\n");
|
DLOG("\t new bar configuration finished, saving.\n");
|
||||||
/* Generate a unique ID for this bar if not already configured */
|
/* Generate a unique ID for this bar if not already configured */
|
||||||
|
|
|
@ -514,6 +514,9 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
ystr("workspace_buttons");
|
ystr("workspace_buttons");
|
||||||
y(bool, !config->hide_workspace_buttons);
|
y(bool, !config->hide_workspace_buttons);
|
||||||
|
|
||||||
|
ystr("strip_workspace_numbers");
|
||||||
|
y(bool, config->strip_workspace_numbers);
|
||||||
|
|
||||||
ystr("binding_mode_indicator");
|
ystr("binding_mode_indicator");
|
||||||
y(bool, !config->hide_binding_mode_indicator);
|
y(bool, !config->hide_binding_mode_indicator);
|
||||||
|
|
||||||
|
|
|
@ -627,7 +627,7 @@ EOT
|
||||||
|
|
||||||
$expected = <<'EOT';
|
$expected = <<'EOT';
|
||||||
cfg_bar_output(LVDS-1)
|
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: (in file <stdin>)
|
||||||
ERROR: CONFIG: Line 1: bar {
|
ERROR: CONFIG: Line 1: bar {
|
||||||
ERROR: CONFIG: Line 2: output LVDS-1
|
ERROR: CONFIG: Line 2: output LVDS-1
|
||||||
|
|
Loading…
Reference in New Issue