diff --git a/doc/rofi-theme.5 b/doc/rofi-theme.5 index cc7b18d5..12edc7fd 100644 --- a/doc/rofi-theme.5 +++ b/doc/rofi-theme.5 @@ -2041,6 +2041,8 @@ It supports the following keys as constraint: \fB\fCmax-aspect-ratio\fR: load when aspect ratio is under value. .IP \(bu 2 \fB\fCmonitor-id\fR: The monitor id, see rofi -help for id's. +.IP \(bu 2 +\fB\fCenabled\fR: Boolean option to enable. Supports environment variable. .RE @@ -2058,6 +2060,17 @@ It supports the following keys as constraint: .fi .RE +.PP +.RS + +.nf +@media ( enabled: env(DO_LIGHT, false ) { + +} + +.fi +.RE + .SH Font Parsing .PP Rofi uses pango diff --git a/doc/rofi-theme.5.markdown b/doc/rofi-theme.5.markdown index 3e6b8899..fd8ff08b 100644 --- a/doc/rofi-theme.5.markdown +++ b/doc/rofi-theme.5.markdown @@ -1308,6 +1308,7 @@ It supports the following keys as constraint: * `min-aspect-ratio` load when aspect ratio is over value. * `max-aspect-ratio`: load when aspect ratio is under value. * `monitor-id`: The monitor id, see rofi -help for id's. + * `enabled`: Boolean option to enable. Supports environment variable. @media takes an integer number or a fraction, for integer number `px` can be added. @@ -1318,6 +1319,12 @@ It supports the following keys as constraint: } ``` +``` +@media ( enabled: env(DO_LIGHT, false ) { + +} +``` + ## Font Parsing diff --git a/include/theme.h b/include/theme.h index 6690e20f..789aa5f3 100644 --- a/include/theme.h +++ b/include/theme.h @@ -50,6 +50,8 @@ typedef enum { THEME_MEDIA_TYPE_MIN_ASPECT_RATIO, /** Maximum aspect ratio constraint. */ THEME_MEDIA_TYPE_MAX_ASPECT_RATIO, + /** Boolean option for use with env. */ + THEME_MEDIA_TYPE_BOOLEAN, /** Invalid entry. */ THEME_MEDIA_TYPE_INVALID, } ThemeMediaType; @@ -60,6 +62,7 @@ typedef enum { typedef struct ThemeMedia { ThemeMediaType type; double value; + gboolean boolv; } ThemeMedia; /** diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l index 8ddbeee4..8edf5eea 100644 --- a/lexer/theme-lexer.l +++ b/lexer/theme-lexer.l @@ -178,7 +178,6 @@ WSO [[:blank:]]* WORD [[:alnum:]-]+ WORD_ELEMENT [[:alpha:]][[:alnum:]-]* WORD_ENV [[:alpha:]_][[:alnum:]_]* -MEDIA_NAME [[:alpha:]-]+ COLOR_NAME [[:alpha:]]+ STRING \"{UANYN}*\" STRING_LIST \"{UANYNP}*\" @@ -291,6 +290,8 @@ MEDIA "@media" CONFIGURATION (?i:configuration) +MEDIA_TYPES (monitor-id|(min|max)-(width|height|aspect-ratio)|enabled) + %x INCLUDE %x PROPERTIES %x PROPERTIES_ENV @@ -301,8 +302,12 @@ CONFIGURATION (?i:configuration) %x NAMESTR %x SECTION %x DEFAULTS +/* Media section.*/ %x MEDIA %x MEDIA_CONTENT +%x MEDIA_ENV_VAR +%x MEDIA_ENV_VAR_CONTENT +%x MEDIA_ENV_VAR_DEFAULT %% %{ @@ -497,11 +502,11 @@ if ( queue == NULL ) { /* After Namestr/Classstr we want to go to state str, then to { */ {WHITESPACE}+ ; // ignore all whitespace -{WHITESPACE}+ ; // ignore all whitespace +{WHITESPACE}+ ; // ignore all whitespace
":" { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES); return T_PSEP; } ";" { BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); return T_PCLOSE;} -(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;} +(true|false) { yylval->bval= g_strcmp0(yytext, "true") == 0; return T_BOOLEAN;} {PNNUMBER}\.{NUMBER}+ { yylval->fval = g_ascii_strtod(yytext, NULL); return T_DOUBLE;} {PNNUMBER} { yylval->ival = (int)g_ascii_strtoll(yytext, NULL, 10); return T_INT;} {STRING} { yytext[yyleng-1] = '\0'; yylval->sval = g_strcompress(&yytext[1]); return T_STRING;} @@ -579,6 +584,25 @@ if ( queue == NULL ) { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(PROPERTIES_ENV); } } +{WORD_ENV} { + const char *val = g_getenv(yytext); + if ( val ) { + ParseObject *top = g_queue_peek_head ( file_queue ); + top->location = *yylloc; + ParseObject *po = g_malloc0(sizeof(ParseObject)); + po->type = PT_ENV; + po->input_str = val; + po->str_len = strlen(val); + current = po; + g_queue_push_head ( file_queue, po ); + + yypush_buffer_state (yy_create_buffer ( 0, YY_BUF_SIZE )); + yylloc->first_line = yylloc->last_line = 1; + yylloc->first_column = yylloc->last_column = 1; + yylloc->filename = current->filename; + g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(MEDIA_ENV_VAR_CONTENT); + } +} /** @@ -641,7 +665,7 @@ if ( queue == NULL ) { {HWB} { return T_COL_HWB; } {CMYK} { return T_COL_CMYK; } -{S_T_PARENT_LEFT} { +{S_T_PARENT_LEFT} { return T_PARENT_LEFT; } /* Fluff */ @@ -655,7 +679,12 @@ if ( queue == NULL ) { BEGIN(PROPERTIES_ENV_VAR); return T_ENV_START; } -{S_T_PARENT_RIGHT} { +{ENV_START} { + g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); + BEGIN(MEDIA_ENV_VAR); + return T_ENV_START; +} +{S_T_PARENT_RIGHT} { BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue ))); return T_PARENT_RIGHT; } @@ -664,7 +693,12 @@ if ( queue == NULL ) { BEGIN(PROPERTIES_VAR_DEFAULT); return T_COMMA; } -{S_T_PARENT_RIGHT} { +{COMMA} { + g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); + BEGIN(MEDIA_ENV_VAR_DEFAULT); + return T_COMMA; +} +{S_T_PARENT_RIGHT} { // Pop 2. g_queue_pop_head ( queue ); BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue ))); @@ -725,7 +759,7 @@ if ( queue == NULL ) { REJECT; } -<> { +<> { ParseObject *po = g_queue_pop_head ( file_queue ); if ( po ) { if ( po->type == PT_FILE ) { @@ -766,15 +800,20 @@ if ( queue == NULL ) { BEGIN(MEDIA); return T_MEDIA; } +"\}" { + g_queue_pop_head ( queue ); + BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue ))); + return T_BCLOSE; +} {S_T_PARENT_LEFT} { g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); BEGIN(MEDIA_CONTENT); return T_PARENT_LEFT; } -{MEDIA_NAME} { +{MEDIA_TYPES} { yylval->sval = g_strdup(yytext); - return T_STRING; + return T_MEDIA_TYPE; } ":" { return T_PSEP; @@ -790,17 +829,14 @@ if ( queue == NULL ) { return T_BOPEN; } -"\}" { - g_queue_pop_head ( queue ); - BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue ))); - return T_BCLOSE; -} -{WHITESPACE}+ ; // ignore all whitespace + /** + * Media defaults. + */ +{WHITESPACE}+ ; // ignore all whitespace -. { +. { yytext[yyleng-1] = '\0'; - fprintf(stderr,"found: |%s|\n", yytext); return T_ERROR; } @@ -827,7 +863,7 @@ if ( queue == NULL ) { return T_ELEMENT; } -. { +. { yytext[yyleng-1] = '\0'; return T_ERROR_PROPERTY; } diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index 455bc1be..494ad368 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -162,7 +162,8 @@ static ThemeColor hwb_to_rgb ( double h, double w, double b ) %token T_ERROR_ARGB_SPEC 7 "invalid argb color. Requires 8 (not 7) elements: argb:AARRGGBB." %token T_INT "Integer number" %token T_DOUBLE "Floating-point number" -%token T_STRING "UTF-8 encoded string" +%token T_STRING "UTF-8 encode string" +%token T_MEDIA_TYPE "Media type" %token T_CHAR "Character" %token T_PROP_NAME "property name" %token T_COLOR_NAME "Color value by name" @@ -387,7 +388,7 @@ t_entry_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE { g_hash_table_destroy ( $4 ); } } -| t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_INT T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_INT T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { gchar *name = g_strdup_printf("@media ( %s: %d )",$4, $6); ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); widget->set = TRUE; @@ -401,7 +402,7 @@ t_entry_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE { g_free ( $4 ); g_free ( name ); } -| t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_DOUBLE T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_DOUBLE T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { gchar *name = g_strdup_printf("@media ( %s: %f )",$4, $6); ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); widget->set = TRUE; @@ -415,7 +416,7 @@ t_entry_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE { g_free ( $4 ); g_free ( name ); } -| t_entry_list T_MEDIA T_PARENT_LEFT T_STRING T_PSEP T_INT T_UNIT_PX T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_INT T_UNIT_PX T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { gchar *name = g_strdup_printf("@media ( %s: %d px )",$4, $6); ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); widget->set = TRUE; @@ -429,6 +430,48 @@ t_entry_list T_CONFIGURATION T_BOPEN t_config_property_list_optional T_BCLOSE { g_free ( $4 ); g_free ( name ); } +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_BOOLEAN T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { + gchar *name = g_strdup_printf("@media ( %s: %s )",$4, $6?"true":"false"); + ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); + widget->set = TRUE; + widget->media = g_slice_new0(ThemeMedia); + widget->media->type = rofi_theme_parse_media_type ( $4 ); + widget->media->boolv = $6; + for ( unsigned int i = 0; i < $9->num_widgets; i++ ) { + ThemeWidget *d = $9->widgets[i]; + rofi_theme_parse_merge_widgets(widget, d); + } + g_free ( $4 ); + g_free ( name ); +} +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_ENV_START T_PARENT_LEFT T_BOOLEAN T_COMMA T_BOOLEAN T_PARENT_RIGHT T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { + gchar *name = g_strdup_printf("@media ( %s: %s )",$4, $8?"true":"false"); + ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); + widget->set = TRUE; + widget->media = g_slice_new0(ThemeMedia); + widget->media->type = rofi_theme_parse_media_type ( $4 ); + widget->media->boolv = $8; + for ( unsigned int i = 0; i < $14->num_widgets; i++ ) { + ThemeWidget *d = $14->widgets[i]; + rofi_theme_parse_merge_widgets(widget, d); + } + g_free ( $4 ); + g_free ( name ); +} +| t_entry_list T_MEDIA T_PARENT_LEFT T_MEDIA_TYPE T_PSEP T_ENV_START T_PARENT_LEFT T_COMMA T_BOOLEAN T_PARENT_RIGHT T_PARENT_RIGHT T_BOPEN t_entry_list T_BCLOSE { + gchar *name = g_strdup_printf("@media ( %s: %s )",$4, $9?"true":"false"); + ThemeWidget *widget = rofi_theme_find_or_create_name ( $1, name ); + widget->set = TRUE; + widget->media = g_slice_new0(ThemeMedia); + widget->media->type = rofi_theme_parse_media_type ( $4 ); + widget->media->boolv = $9; + for ( unsigned int i = 0; i < $13->num_widgets; i++ ) { + ThemeWidget *d = $13->widgets[i]; + rofi_theme_parse_merge_widgets(widget, d); + } + g_free ( $4 ); + g_free ( name ); +} ; t_config_property_list_optional diff --git a/source/theme.c b/source/theme.c index 11bd0509..83556c2f 100644 --- a/source/theme.c +++ b/source/theme.c @@ -1532,6 +1532,15 @@ static void rofi_theme_parse_process_conditionals_int(workarea mon, } break; } + case THEME_MEDIA_TYPE_BOOLEAN: { + if (widget->media->boolv) { + for (unsigned int x = 0; x < widget->num_widgets; x++) { + rofi_theme_parse_merge_widgets(rwidget, widget->widgets[x]); + } + } + break; + } + default: { break; } @@ -1625,6 +1634,9 @@ ThemeMediaType rofi_theme_parse_media_type(const char *type) { if (g_strcmp0(type, "max-aspect-ratio") == 0) { return THEME_MEDIA_TYPE_MAX_ASPECT_RATIO; } + if (g_strcmp0(type, "enabled") == 0) { + return THEME_MEDIA_TYPE_BOOLEAN; + } return THEME_MEDIA_TYPE_INVALID; }