From 57baad4afde8d1bab4040c5a5cbe8a5b367bceba Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 7 Apr 2018 15:36:39 +1000 Subject: [PATCH] Make FaceRegistry scoped set-face now takes a scope argument, and faces can be overridden on a buffer or window basis. colorscheme apply on global scope, which should be good enough for now. Fixes #1411 --- colors/base16.kak | 86 ++++++++++++++++++------------------ colors/default.kak | 86 ++++++++++++++++++------------------ colors/desertex.kak | 84 +++++++++++++++++------------------ colors/github.kak | 80 ++++++++++++++++----------------- colors/gruvbox.kak | 88 ++++++++++++++++++------------------- colors/lucius.kak | 86 ++++++++++++++++++------------------ colors/reeder.kak | 86 ++++++++++++++++++------------------ colors/solarized-dark.kak | 88 ++++++++++++++++++------------------- colors/solarized-light.kak | 88 ++++++++++++++++++------------------- colors/tomorrow-night.kak | 86 ++++++++++++++++++------------------ colors/zenburn.kak | 86 ++++++++++++++++++------------------ doc/pages/commands.asciidoc | 7 ++- rc/base/mercurial.kak | 2 +- rc/core/kakrc.kak | 4 +- rc/extra/git-tools.kak | 4 +- src/alias_registry.hh | 2 +- src/client.cc | 28 +++++++----- src/client_manager.cc | 3 +- src/commands.cc | 40 ++++++++++++----- src/context.cc | 6 +-- src/context.hh | 3 +- src/display_buffer.cc | 5 ++- src/display_buffer.hh | 4 +- src/face_registry.cc | 43 +++++++++--------- src/face_registry.hh | 46 +++++++++++-------- src/highlighter.cc | 55 +++++++++++++++++++++++ src/highlighter.hh | 26 ++++------- src/highlighters.cc | 67 ++++++++++++---------------- src/hook_manager.cc | 2 +- src/input_handler.cc | 49 ++++++++++++--------- src/insert_completer.cc | 26 +++++++---- src/insert_completer.hh | 14 +++--- src/main.cc | 6 +-- src/normal.cc | 32 +++++++------- src/scope.hh | 7 ++- src/shell_manager.cc | 2 +- 36 files changed, 760 insertions(+), 667 deletions(-) create mode 100644 src/highlighter.cc diff --git a/colors/base16.kak b/colors/base16.kak index 6284df5e..055b5d95 100644 --- a/colors/base16.kak +++ b/colors/base16.kak @@ -18,56 +18,56 @@ ## code echo " - face value ${orange_dark}+b - face type ${orange_light} - face variable ${magenta_dark} - face module ${green_dark} - face function ${cyan_light} - face string ${green_dark} - face keyword ${purple_dark}+b - face operator ${cyan_light} - face attribute ${orange_dark} - face comment ${grey_dark} - face meta ${orange_light} - face builtin default+b + face global value ${orange_dark}+b + face global type ${orange_light} + face global variable ${magenta_dark} + face global module ${green_dark} + face global function ${cyan_light} + face global string ${green_dark} + face global keyword ${purple_dark}+b + face global operator ${cyan_light} + face global attribute ${orange_dark} + face global comment ${grey_dark} + face global meta ${orange_light} + face global builtin default+b " ## markup echo " - face title blue - face header ${cyan_light} - face bold ${orange_light} - face italic ${orange_dark} - face mono ${green_dark} - face block ${orange_dark} - face link blue - face bullet ${magenta_light} - face list ${magenta_dark} + face global title blue + face global header ${cyan_light} + face global bold ${orange_light} + face global italic ${orange_dark} + face global mono ${green_dark} + face global block ${orange_dark} + face global link blue + face global bullet ${magenta_light} + face global list ${magenta_dark} " ## builtin echo " - face Default ${grey_light},${black_lighter} - face PrimarySelection white,blue - face SecondarySelection black,blue - face PrimaryCursor black,white - face SecondaryCursor black,white - face PrimaryCursorEol black,${cyan_light} - face SecondaryCursorEol black,${cyan_light} - face LineNumbers ${grey_light},${black_lighter} - face LineNumberCursor ${grey_light},rgb:282828+b - face MenuForeground ${grey_light},blue - face MenuBackground blue,${grey_light} - face MenuInfo ${cyan_light} - face Information ${black_light},${cyan_light} - face Error ${grey_light},${magenta_light} - face StatusLine ${grey_light},${black_lighterer} - face StatusLineMode ${orange_dark} - face StatusLineInfo ${cyan_light} - face StatusLineValue ${green_dark} - face StatusCursor ${black_lighterer},${cyan_light} - face Prompt ${black_light},${cyan_light} - face MatchingChar ${cyan_light},${black_light}+b - face BufferPadding ${cyan_light},${black_lighter} + face global Default ${grey_light},${black_lighter} + face global PrimarySelection white,blue + face global SecondarySelection black,blue + face global PrimaryCursor black,white + face global SecondaryCursor black,white + face global PrimaryCursorEol black,${cyan_light} + face global SecondaryCursorEol black,${cyan_light} + face global LineNumbers ${grey_light},${black_lighter} + face global LineNumberCursor ${grey_light},rgb:282828+b + face global MenuForeground ${grey_light},blue + face global MenuBackground blue,${grey_light} + face global MenuInfo ${cyan_light} + face global Information ${black_light},${cyan_light} + face global Error ${grey_light},${magenta_light} + face global StatusLine ${grey_light},${black_lighterer} + face global StatusLineMode ${orange_dark} + face global StatusLineInfo ${cyan_light} + face global StatusLineValue ${green_dark} + face global StatusCursor ${black_lighterer},${cyan_light} + face global Prompt ${black_light},${cyan_light} + face global MatchingChar ${cyan_light},${black_light}+b + face global BufferPadding ${cyan_light},${black_lighter} " } diff --git a/colors/default.kak b/colors/default.kak index 4a00045c..518c86d3 100644 --- a/colors/default.kak +++ b/colors/default.kak @@ -1,50 +1,50 @@ # Kakoune default color scheme # For Code -face value red -face type yellow -face variable green -face module green -face function cyan -face string magenta -face keyword blue -face operator yellow -face attribute green -face comment cyan -face meta magenta -face builtin default+b +face global value red +face global type yellow +face global variable green +face global module green +face global function cyan +face global string magenta +face global keyword blue +face global operator yellow +face global attribute green +face global comment cyan +face global meta magenta +face global builtin default+b # For markup -face title blue -face header cyan -face bold red -face italic yellow -face mono green -face block magenta -face link cyan -face bullet cyan -face list yellow +face global title blue +face global header cyan +face global bold red +face global italic yellow +face global mono green +face global block magenta +face global link cyan +face global bullet cyan +face global list yellow # builtin faces -face Default default,default -face PrimarySelection white,blue -face SecondarySelection black,blue -face PrimaryCursor black,white -face SecondaryCursor black,white -face PrimaryCursorEol black,cyan -face SecondaryCursorEol black,cyan -face LineNumbers default,default -face LineNumberCursor default,default+r -face MenuForeground white,blue -face MenuBackground blue,white -face MenuInfo cyan -face Information black,yellow -face Error black,red -face StatusLine cyan,default -face StatusLineMode yellow,default -face StatusLineInfo blue,default -face StatusLineValue green,default -face StatusCursor black,cyan -face Prompt yellow,default -face MatchingChar default,default+b -face BufferPadding blue,default +face global Default default,default +face global PrimarySelection white,blue +face global SecondarySelection black,blue +face global PrimaryCursor black,white +face global SecondaryCursor black,white +face global PrimaryCursorEol black,cyan +face global SecondaryCursorEol black,cyan +face global LineNumbers default,default +face global LineNumberCursor default,default+r +face global MenuForeground white,blue +face global MenuBackground blue,white +face global MenuInfo cyan +face global Information black,yellow +face global Error black,red +face global StatusLine cyan,default +face global StatusLineMode yellow,default +face global StatusLineInfo blue,default +face global StatusLineValue green,default +face global StatusCursor black,cyan +face global Prompt yellow,default +face global MatchingChar default,default+b +face global BufferPadding blue,default diff --git a/colors/desertex.kak b/colors/desertex.kak index 25981320..b1fe21dd 100644 --- a/colors/desertex.kak +++ b/colors/desertex.kak @@ -1,79 +1,79 @@ # desertex theme # Code -face value rgb:fa8072 -face type rgb:dfdfbf -face identifier rgb:87ceeb -face string rgb:fa8072 -face error rgb:c3bf9f+b -face keyword rgb:eedc82 -face operator rgb:87ceeb -face attribute rgb:eedc82 -face comment rgb:7ccd7c+i +face global value rgb:fa8072 +face global type rgb:dfdfbf +face global identifier rgb:87ceeb +face global string rgb:fa8072 +face global error rgb:c3bf9f+b +face global keyword rgb:eedc82 +face global operator rgb:87ceeb +face global attribute rgb:eedc82 +face global comment rgb:7ccd7c+i # #include <...> -face meta rgb:ee799f +face global meta rgb:ee799f # Markup -face title blue -face header cyan -face bold red -face italic yellow -face mono green -face block magenta -face link cyan -face bullet cyan -face list yellow +face global title blue +face global header cyan +face global bold red +face global italic yellow +face global mono green +face global block magenta +face global link cyan +face global bullet cyan +face global list yellow # Builtin # fg,bg+attributes -# face Default default,rgb:262626 <- change the terminal bg color instead -face Default default,default +# face global Default default,rgb:262626 <- change the terminal bg color instead +face global Default default,default -face PrimarySelection white,blue -face SecondarySelection black,blue +face global PrimarySelection white,blue +face global SecondarySelection black,blue -face PrimaryCursor black,white -face SecondaryCursor black,white +face global PrimaryCursor black,white +face global SecondaryCursor black,white -face PrimaryCursorEol black,rgb:7ccd7c -face SecondaryCursorEol black,rgb:7ccd7c +face global PrimaryCursorEol black,rgb:7ccd7c +face global SecondaryCursorEol black,rgb:7ccd7c -face LineNumbers rgb:605958 -face LineNumberCursor yellow,default+b +face global LineNumbers rgb:605958 +face global LineNumberCursor yellow,default+b # Bottom menu: # text + background -face MenuBackground black,rgb:c2bfa5+b +face global MenuBackground black,rgb:c2bfa5+b # selected entry in the menu (use 302028 when true color support is fixed) -face MenuForeground rgb:f0a0c0,magenta +face global MenuForeground rgb:f0a0c0,magenta # completion menu info -face MenuInfo white,rgb:445599 +face global MenuInfo white,rgb:445599 # assistant, [+] -face Information black,yellow +face global Information black,yellow -face Error white,red -face StatusLine cyan,default +face global Error white,red +face global StatusLine cyan,default # Status line modes and prompts: # insert, prompt, enter key... -face StatusLineMode rgb:ffd75f,default +face global StatusLineMode rgb:ffd75f,default # 1 sel -face StatusLineInfo blue,default +face global StatusLineInfo blue,default # param=value, reg=value. ex: "ey -face StatusLineValue green,default +face global StatusLineValue green,default -face StatusCursor black,cyan +face global StatusCursor black,cyan # : -face Prompt blue +face global Prompt blue # (), {} -face MatchingChar cyan+b +face global MatchingChar cyan+b # EOF tildas (~) -face BufferPadding blue,default +face global BufferPadding blue,default diff --git a/colors/github.kak b/colors/github.kak index ae5bb934..75a5be57 100644 --- a/colors/github.kak +++ b/colors/github.kak @@ -4,47 +4,47 @@ ## ## code -face value rgb:0086B3+b -face type rgb:795DA3 -face variable rgb:0086B3 -face module rgb:0086B3 -face function rgb:A71D5D -face string rgb:183691 -face keyword rgb:A71D5D+b -face operator yellow -face attribute rgb:A71D5D -face comment rgb:AAAAAA -face meta rgb:183691 -face builtin default+b +face global value rgb:0086B3+b +face global type rgb:795DA3 +face global variable rgb:0086B3 +face global module rgb:0086B3 +face global function rgb:A71D5D +face global string rgb:183691 +face global keyword rgb:A71D5D+b +face global operator yellow +face global attribute rgb:A71D5D +face global comment rgb:AAAAAA +face global meta rgb:183691 +face global builtin default+b ## markup -face title blue -face header cyan -face bold red -face italic yellow -face mono green -face block magenta -face link cyan -face bullet cyan -face list yellow +face global title blue +face global header cyan +face global bold red +face global italic yellow +face global mono green +face global block magenta +face global link cyan +face global bullet cyan +face global list yellow ## builtin -face Default rgb:121213,rgb:F8F8FF -face PrimarySelection default,rgb:A6F3A6 -face SecondarySelection default,rgb:DBFFDB -face PrimaryCursor black,rgb:888888 -face SecondaryCursor black,rgb:888888 -face PrimaryCursorEol black,rgb:A71D5D -face SecondaryCursorEol black,rgb:A71D5D -face LineNumbers rgb:A0A0A0,rgb:ECECEC -face LineNumberCursor rgb:434343,rgb:DDDDDD -face MenuForeground rgb:434343,rgb:CDCDFD -face MenuBackground rgb:F8F8FF,rgb:808080 -face Information rgb:F8F8FF,rgb:4078C0 -face Error rgb:F8F8FF,rgb:BD2C00 -face StatusLine rgb:434343,rgb:DDDDDD -face StatusCursor rgb:434343,rgb:CDCDFD -face Prompt rgb:F8F8FF,rgb:4078C0 -face MatchingChar rgb:F8F8FF,rgb:4078C0+b -face Search default,default+u -face BufferPadding rgb:A0A0A0,rgb:F8F8FF +face global Default rgb:121213,rgb:F8F8FF +face global PrimarySelection default,rgb:A6F3A6 +face global SecondarySelection default,rgb:DBFFDB +face global PrimaryCursor black,rgb:888888 +face global SecondaryCursor black,rgb:888888 +face global PrimaryCursorEol black,rgb:A71D5D +face global SecondaryCursorEol black,rgb:A71D5D +face global LineNumbers rgb:A0A0A0,rgb:ECECEC +face global LineNumberCursor rgb:434343,rgb:DDDDDD +face global MenuForeground rgb:434343,rgb:CDCDFD +face global MenuBackground rgb:F8F8FF,rgb:808080 +face global Information rgb:F8F8FF,rgb:4078C0 +face global Error rgb:F8F8FF,rgb:BD2C00 +face global StatusLine rgb:434343,rgb:DDDDDD +face global StatusCursor rgb:434343,rgb:CDCDFD +face global Prompt rgb:F8F8FF,rgb:4078C0 +face global MatchingChar rgb:F8F8FF,rgb:4078C0+b +face global Search default,default+u +face global BufferPadding rgb:A0A0A0,rgb:F8F8FF diff --git a/colors/gruvbox.kak b/colors/gruvbox.kak index a3559af2..315a338e 100644 --- a/colors/gruvbox.kak +++ b/colors/gruvbox.kak @@ -24,52 +24,52 @@ echo " # Code highlighting - face value ${purple} - face type ${yellow} - face variable ${blue} - face module ${green} - face function default - face string ${green} - face keyword ${red} - face operator default - face attribute ${orange} - face comment ${gray} - face meta ${aqua} - face builtin default+b + face global value ${purple} + face global type ${yellow} + face global variable ${blue} + face global module ${green} + face global function default + face global string ${green} + face global keyword ${red} + face global operator default + face global attribute ${orange} + face global comment ${gray} + face global meta ${aqua} + face global builtin default+b # Markdown highlighting - face title ${green}+b - face header ${orange} - face bold ${fg}+b - face italic ${fg3} - face mono ${fg4} - face block default - face link default - face bullet default - face list default + face global title ${green}+b + face global header ${orange} + face global bold ${fg}+b + face global italic ${fg3} + face global mono ${fg4} + face global block default + face global link default + face global bullet default + face global list default - face Default ${fg},${bg} - face PrimarySelection ${fg},${blue} - face SecondarySelection ${bg},${blue} - face PrimaryCursor ${bg},${fg} - face SecondaryCursor ${bg},${fg} - face PrimaryCursorEol ${bg},${fg4} - face SecondaryCursorEol ${bg},${fg4} - face LineNumbers ${bg4} - face LineNumberCursor ${yellow},${bg1} - face MenuForeground ${bg2},${blue} - face MenuBackground default,${bg2} - face MenuInfo ${bg} - face Information ${bg},${fg} - face Error default,${red} - face StatusLine default - face StatusLineMode ${yellow}+b - face StatusLineInfo ${purple} - face StatusLineValue ${red} - face StatusCursor ${bg},${fg} - face Prompt ${yellow} - face MatchingChar default+b - face BufferPadding ${bg2},${bg} - face Whitespace ${bg2} + face global Default ${fg},${bg} + face global PrimarySelection ${fg},${blue} + face global SecondarySelection ${bg},${blue} + face global PrimaryCursor ${bg},${fg} + face global SecondaryCursor ${bg},${fg} + face global PrimaryCursorEol ${bg},${fg4} + face global SecondaryCursorEol ${bg},${fg4} + face global LineNumbers ${bg4} + face global LineNumberCursor ${yellow},${bg1} + face global MenuForeground ${bg2},${blue} + face global MenuBackground default,${bg2} + face global MenuInfo ${bg} + face global Information ${bg},${fg} + face global Error default,${red} + face global StatusLine default + face global StatusLineMode ${yellow}+b + face global StatusLineInfo ${purple} + face global StatusLineValue ${red} + face global StatusCursor ${bg},${fg} + face global Prompt ${yellow} + face global MatchingChar default+b + face global BufferPadding ${bg2},${bg} + face global Whitespace ${bg2} " } diff --git a/colors/lucius.kak b/colors/lucius.kak index 0d8e7318..8ca99c6e 100644 --- a/colors/lucius.kak +++ b/colors/lucius.kak @@ -24,52 +24,52 @@ echo " # then we map them to code - face value ${lucius_light_green} - face type ${lucius_blue} - face variable ${lucius_green} - face module ${lucius_green} - face function ${lucius_light_blue} - face string ${lucius_light_green} - face keyword ${lucius_light_blue} - face operator ${lucius_green} - face attribute ${lucius_light_blue} - face comment ${lucius_grey} - face meta ${lucius_purple} - face builtin default+b + face global value ${lucius_light_green} + face global type ${lucius_blue} + face global variable ${lucius_green} + face global module ${lucius_green} + face global function ${lucius_light_blue} + face global string ${lucius_light_green} + face global keyword ${lucius_light_blue} + face global operator ${lucius_green} + face global attribute ${lucius_light_blue} + face global comment ${lucius_grey} + face global meta ${lucius_purple} + face global builtin default+b # and markup - face title ${lucius_light_blue} - face header ${lucius_light_green} - face bold ${lucius_blue} - face italic ${lucius_green} - face mono ${lucius_light_green} - face block ${lucius_light_blue} - face link ${lucius_light_green} - face bullet ${lucius_green} - face list ${lucius_blue} + face global title ${lucius_light_blue} + face global header ${lucius_light_green} + face global bold ${lucius_blue} + face global italic ${lucius_green} + face global mono ${lucius_light_green} + face global block ${lucius_light_blue} + face global link ${lucius_light_green} + face global bullet ${lucius_green} + face global list ${lucius_blue} # and built in faces - face Default ${lucius_lighter_grey},${lucius_darker_grey} - face PrimarySelection ${lucius_darker_grey},${lucius_orange} - face SecondarySelection ${lucius_lighter_grey},${lucius_dark_blue} - face PrimaryCursor ${lucius_darker_grey},${lucius_lighter_grey} - face SecondaryCursor ${lucius_darker_grey},${lucius_lighter_grey} - face PrimaryCursorEol ${lucius_darker_grey},${lucius_dark_green} - face SecondaryCursorEol ${lucius_darker_grey},${lucius_dark_green} - face LineNumbers ${lucius_grey},${lucius_dark_grey} - face LineNumberCursor ${lucius_grey},${lucius_dark_grey}+b - face MenuForeground ${lucius_blue},${lucius_dark_blue} - face MenuBackground ${lucius_darker_grey},${lucius_light_grey} - face MenuInfo ${lucius_grey} - face Information ${lucius_lighter_grey},${lucius_dark_green} - face Error ${lucius_light_red},${lucius_dark_red} - face StatusLine ${lucius_lighter_grey},${lucius_dark_grey} - face StatusLineMode ${lucius_lighter_grey},${lucius_dark_green}+b - face StatusLineInfo ${lucius_dark_grey},${lucius_lighter_grey} - face StatusLineValue ${lucius_lighter_grey} - face StatusCursor default,${lucius_blue} - face Prompt ${lucius_lighter_grey} - face MatchingChar ${lucius_lighter_grey},${lucius_bright_green} - face BufferPadding ${lucius_green},${lucius_darker_grey} + face global Default ${lucius_lighter_grey},${lucius_darker_grey} + face global PrimarySelection ${lucius_darker_grey},${lucius_orange} + face global SecondarySelection ${lucius_lighter_grey},${lucius_dark_blue} + face global PrimaryCursor ${lucius_darker_grey},${lucius_lighter_grey} + face global SecondaryCursor ${lucius_darker_grey},${lucius_lighter_grey} + face global PrimaryCursorEol ${lucius_darker_grey},${lucius_dark_green} + face global SecondaryCursorEol ${lucius_darker_grey},${lucius_dark_green} + face global LineNumbers ${lucius_grey},${lucius_dark_grey} + face global LineNumberCursor ${lucius_grey},${lucius_dark_grey}+b + face global MenuForeground ${lucius_blue},${lucius_dark_blue} + face global MenuBackground ${lucius_darker_grey},${lucius_light_grey} + face global MenuInfo ${lucius_grey} + face global Information ${lucius_lighter_grey},${lucius_dark_green} + face global Error ${lucius_light_red},${lucius_dark_red} + face global StatusLine ${lucius_lighter_grey},${lucius_dark_grey} + face global StatusLineMode ${lucius_lighter_grey},${lucius_dark_green}+b + face global StatusLineInfo ${lucius_dark_grey},${lucius_lighter_grey} + face global StatusLineValue ${lucius_lighter_grey} + face global StatusCursor default,${lucius_blue} + face global Prompt ${lucius_lighter_grey} + face global MatchingChar ${lucius_lighter_grey},${lucius_bright_green} + face global BufferPadding ${lucius_green},${lucius_darker_grey} " } diff --git a/colors/reeder.kak b/colors/reeder.kak index bf52291e..dd19cd24 100644 --- a/colors/reeder.kak +++ b/colors/reeder.kak @@ -22,52 +22,52 @@ # Base color definitions echo " # then we map them to code - face value ${orange_light}+b - face type ${orange} - face variable default - face module ${green} - face function default - face string ${green} - face keyword ${brown_dark} - face operator default - face attribute ${green} - face comment ${brown_light} - face meta ${brown_dark} - face builtin default+b + face global value ${orange_light}+b + face global type ${orange} + face global variable default + face global module ${green} + face global function default + face global string ${green} + face global keyword ${brown_dark} + face global operator default + face global attribute ${green} + face global comment ${brown_light} + face global meta ${brown_dark} + face global builtin default+b # and markup - face title ${orange}+b - face header ${orange}+b - face bold default+b - face italic default+i - face mono ${green_light} - face block ${green} - face link ${orange} - face bullet ${brown_dark} - face list ${black} + face global title ${orange}+b + face global header ${orange}+b + face global bold default+b + face global italic default+i + face global mono ${green_light} + face global block ${green} + face global link ${orange} + face global bullet ${brown_dark} + face global list ${black} # and built in faces - face Default ${black_light},${white} - face PrimarySelection ${black},${brown_lighter} - face SecondarySelection ${black_light},${grey_light} - face PrimaryCursor ${black},${grey_dark} - face SecondaryCursor ${black},${grey_dark} - face PrimaryCursorEol ${black},${brown_dark} - face SecondaryCursorEol ${black},${brown_dark} - face LineNumbers ${grey_dark},${white} - face LineNumberCursor ${grey_dark},${brown_lighter} - face MenuForeground ${orange},${brown_lighter} - face MenuBackground ${black_light},${brown_lighter} - face MenuInfo default,${black} - face Information ${black_light},${brown_lighter} - face Error default,${red} - face StatusLine ${black},${grey_light} - face StatusLineMode ${orange} - face StatusLineInfo ${black}+b - face StatusLineValue ${green_light} - face StatusCursor ${orange},${white_light} - face Prompt ${black_light} - face MatchingChar default+b - face BufferPadding ${grey_dark},${white} + face global Default ${black_light},${white} + face global PrimarySelection ${black},${brown_lighter} + face global SecondarySelection ${black_light},${grey_light} + face global PrimaryCursor ${black},${grey_dark} + face global SecondaryCursor ${black},${grey_dark} + face global PrimaryCursorEol ${black},${brown_dark} + face global SecondaryCursorEol ${black},${brown_dark} + face global LineNumbers ${grey_dark},${white} + face global LineNumberCursor ${grey_dark},${brown_lighter} + face global MenuForeground ${orange},${brown_lighter} + face global MenuBackground ${black_light},${brown_lighter} + face global MenuInfo default,${black} + face global Information ${black_light},${brown_lighter} + face global Error default,${red} + face global StatusLine ${black},${grey_light} + face global StatusLineMode ${orange} + face global StatusLineInfo ${black}+b + face global StatusLineValue ${green_light} + face global StatusCursor ${orange},${white_light} + face global Prompt ${black_light} + face global MatchingChar default+b + face global BufferPadding ${grey_dark},${white} " } diff --git a/colors/solarized-dark.kak b/colors/solarized-dark.kak index 93e24831..67598329 100644 --- a/colors/solarized-dark.kak +++ b/colors/solarized-dark.kak @@ -20,53 +20,53 @@ echo " # code - face value ${cyan} - face type ${yellow} - face variable ${blue} - face module ${cyan} - face function ${blue} - face string ${cyan} - face keyword ${green} - face operator ${green} - face attribute ${violet} - face comment ${base01} - face meta ${orange} - face builtin default+b + face global value ${cyan} + face global type ${yellow} + face global variable ${blue} + face global module ${cyan} + face global function ${blue} + face global string ${cyan} + face global keyword ${green} + face global operator ${green} + face global attribute ${violet} + face global comment ${base01} + face global meta ${orange} + face global builtin default+b # markup - face title ${blue}+b - face header ${blue} - face bold ${base0}+b - face italic ${base0}+i - face mono ${base1} - face block ${cyan} - face link ${base1} - face bullet ${yellow} - face list ${green} + face global title ${blue}+b + face global header ${blue} + face global bold ${base0}+b + face global italic ${base0}+i + face global mono ${base1} + face global block ${cyan} + face global link ${base1} + face global bullet ${yellow} + face global list ${green} # builtin - face Default ${base0},${base03} - face PrimarySelection ${base03},${blue} - face SecondarySelection ${base01},${base1} - face PrimaryCursor ${base03},${base0} - face SecondaryCursor ${base03},${base01} - face PrimaryCursorEol ${base03},${base2} - face SecondaryCursorEol ${base03},${base3} - face LineNumbers ${base01},${base02} - face LineNumberCursor ${base1},${base02} - face LineNumbersWrapped ${base02},${base02} - face MenuForeground ${base03},${yellow} - face MenuBackground ${base1},${base02} - face MenuInfo ${base01} - face Information ${base02},${base1} - face Error ${red},default+b - face StatusLine ${base1},${base02}+b - face StatusLineMode ${orange} - face StatusLineInfo ${cyan} - face StatusLineValue ${green} - face StatusCursor ${base00},${base3} - face Prompt ${yellow}+b - face MatchingChar ${red},${base01}+b - face BufferPadding ${base01},${base03} + face global Default ${base0},${base03} + face global PrimarySelection ${base03},${blue} + face global SecondarySelection ${base01},${base1} + face global PrimaryCursor ${base03},${base0} + face global SecondaryCursor ${base03},${base01} + face global PrimaryCursorEol ${base03},${base2} + face global SecondaryCursorEol ${base03},${base3} + face global LineNumbers ${base01},${base02} + face global LineNumberCursor ${base1},${base02} + face global LineNumbersWrapped ${base02},${base02} + face global MenuForeground ${base03},${yellow} + face global MenuBackground ${base1},${base02} + face global MenuInfo ${base01} + face global Information ${base02},${base1} + face global Error ${red},default+b + face global StatusLine ${base1},${base02}+b + face global StatusLineMode ${orange} + face global StatusLineInfo ${cyan} + face global StatusLineValue ${green} + face global StatusCursor ${base00},${base3} + face global Prompt ${yellow}+b + face global MatchingChar ${red},${base01}+b + face global BufferPadding ${base01},${base03} " } diff --git a/colors/solarized-light.kak b/colors/solarized-light.kak index 979f9151..9f357794 100644 --- a/colors/solarized-light.kak +++ b/colors/solarized-light.kak @@ -20,53 +20,53 @@ echo " # code - face value ${cyan} - face type ${yellow} - face variable ${blue} - face module ${cyan} - face function ${blue} - face string ${cyan} - face keyword ${green} - face operator ${green} - face attribute ${violet} - face comment ${base1} - face meta ${orange} - face builtin default+b + face global value ${cyan} + face global type ${yellow} + face global variable ${blue} + face global module ${cyan} + face global function ${blue} + face global string ${cyan} + face global keyword ${green} + face global operator ${green} + face global attribute ${violet} + face global comment ${base1} + face global meta ${orange} + face global builtin default+b # markup - face title ${blue}+b - face header ${blue} - face bold ${base01}+b - face italic ${base01}+i - face mono ${base1} - face block ${cyan} - face link ${base01} - face bullet ${yellow} - face list ${green} + face global title ${blue}+b + face global header ${blue} + face global bold ${base01}+b + face global italic ${base01}+i + face global mono ${base1} + face global block ${cyan} + face global link ${base01} + face global bullet ${yellow} + face global list ${green} # builtin - face Default ${base00},${base3} - face PrimarySelection ${base3},${blue} - face SecondarySelection ${base1},${base01} - face PrimaryCursor ${base3},${base00} - face SecondaryCursor ${base3},${base1} - face PrimaryCursorEol ${base3},${yellow} - face SecondaryCursorEol ${base3},${orange} - face LineNumbers ${base1},${base2} - face LineNumberCursor ${base01},${base2} - face LineNumbersWrapped ${base2},${base2} - face MenuForeground ${base3},${yellow} - face MenuBackground ${base01},${base2} - face MenuInfo ${base1} - face Information ${base2},${base1} - face Error ${red},default+b - face StatusLine ${base01},${base2}+b - face StatusLineMode ${orange} - face StatusLineInfo ${cyan} - face StatusLineValue ${green} - face StatusCursor ${base0},${base03} - face Prompt ${yellow}+b - face MatchingChar ${red},${base2}+b - face BufferPadding ${base1},${base3} + face global Default ${base00},${base3} + face global PrimarySelection ${base3},${blue} + face global SecondarySelection ${base1},${base01} + face global PrimaryCursor ${base3},${base00} + face global SecondaryCursor ${base3},${base1} + face global PrimaryCursorEol ${base3},${yellow} + face global SecondaryCursorEol ${base3},${orange} + face global LineNumbers ${base1},${base2} + face global LineNumberCursor ${base01},${base2} + face global LineNumbersWrapped ${base2},${base2} + face global MenuForeground ${base3},${yellow} + face global MenuBackground ${base01},${base2} + face global MenuInfo ${base1} + face global Information ${base2},${base1} + face global Error ${red},default+b + face global StatusLine ${base01},${base2}+b + face global StatusLineMode ${orange} + face global StatusLineInfo ${cyan} + face global StatusLineValue ${green} + face global StatusCursor ${base0},${base03} + face global Prompt ${yellow}+b + face global MatchingChar ${red},${base2}+b + face global BufferPadding ${base1},${base3} " } diff --git a/colors/tomorrow-night.kak b/colors/tomorrow-night.kak index 065a45a1..59065ff6 100644 --- a/colors/tomorrow-night.kak +++ b/colors/tomorrow-night.kak @@ -23,56 +23,56 @@ ## code echo " - face value ${orange} - face type ${yellow} - face variable ${magenta} - face module ${green} - face function ${aqua} - face string ${green_dark} - face keyword ${purple} - face operator ${aqua} - face attribute ${purple} - face comment ${comment} - face meta ${purple} - face builtin ${orange} + face global value ${orange} + face global type ${yellow} + face global variable ${magenta} + face global module ${green} + face global function ${aqua} + face global string ${green_dark} + face global keyword ${purple} + face global operator ${aqua} + face global attribute ${purple} + face global comment ${comment} + face global meta ${purple} + face global builtin ${orange} " ## markup echo " - face title blue - face header ${aqua} - face bold ${yellow} - face italic ${orange} - face mono ${green_dark} - face block ${orange} - face link blue - face bullet ${red} - face list ${red} + face global title blue + face global header ${aqua} + face global bold ${yellow} + face global italic ${orange} + face global mono ${green_dark} + face global block ${orange} + face global link blue + face global bullet ${red} + face global list ${red} " ## builtin echo " - face Default ${text},${background} - face PrimarySelection default,${selection} - face SecondarySelection default,${selection} - face PrimaryCursor black,${aqua} - face SecondaryCursor black,${aqua} - face PrimaryCursorEol black,${green_dark} - face SecondaryCursorEol black,${green_dark} - face LineNumbers ${text_light},${background} - face LineNumberCursor ${yellow},rgb:282828+b - face MenuForeground ${text_light},blue - face MenuBackground ${aqua},${window} - face MenuInfo ${aqua} - face Information white,${window} - face Error white,${red} - face StatusLine ${text},${window} - face StatusLineMode ${yellow}+b - face StatusLineInfo ${aqua} - face StatusLineValue ${green_dark} - face StatusCursor ${window},${aqua} - face Prompt ${background},${aqua} - face MatchingChar ${yellow},${background}+b - face BufferPadding ${aqua},${background} + face global Default ${text},${background} + face global PrimarySelection default,${selection} + face global SecondarySelection default,${selection} + face global PrimaryCursor black,${aqua} + face global SecondaryCursor black,${aqua} + face global PrimaryCursorEol black,${green_dark} + face global SecondaryCursorEol black,${green_dark} + face global LineNumbers ${text_light},${background} + face global LineNumberCursor ${yellow},rgb:282828+b + face global MenuForeground ${text_light},blue + face global MenuBackground ${aqua},${window} + face global MenuInfo ${aqua} + face global Information white,${window} + face global Error white,${red} + face global StatusLine ${text},${window} + face global StatusLineMode ${yellow}+b + face global StatusLineInfo ${aqua} + face global StatusLineValue ${green_dark} + face global StatusCursor ${window},${aqua} + face global Prompt ${background},${aqua} + face global MatchingChar ${yellow},${background}+b + face global BufferPadding ${aqua},${background} " } diff --git a/colors/zenburn.kak b/colors/zenburn.kak index 5f8fc689..ac7f2ab9 100644 --- a/colors/zenburn.kak +++ b/colors/zenburn.kak @@ -31,52 +31,52 @@ echo " # then we map them to code - face value ${zenconstant} - face type ${zentype} - face variable ${zenvariable} - face module ${zenstring} - face function ${zenfunction} - face string ${zenstring} - face keyword ${zenkeyword} - face operator ${zenfunction} - face attribute ${zenstatement} - face comment ${zencomment} - face meta ${zenspecial} - face builtin default+b + face global value ${zenconstant} + face global type ${zentype} + face global variable ${zenvariable} + face global module ${zenstring} + face global function ${zenfunction} + face global string ${zenstring} + face global keyword ${zenkeyword} + face global operator ${zenfunction} + face global attribute ${zenstatement} + face global comment ${zencomment} + face global meta ${zenspecial} + face global builtin default+b # and markup - face title ${zenkeyword} - face header ${zenconstant} - face bold ${zenstorageClass} - face italic ${zenfunction} - face mono ${zennumber} - face block ${zenstatement} - face link ${zenstring} - face bullet ${zenvariable} - face list ${zentype} + face global title ${zenkeyword} + face global header ${zenconstant} + face global bold ${zenstorageClass} + face global italic ${zenfunction} + face global mono ${zennumber} + face global block ${zenstatement} + face global link ${zenstring} + face global bullet ${zenvariable} + face global list ${zentype} # and built in faces - face Default ${zendefault} - face PrimarySelection ${zentext},${zenselectionbg} - face SecondarySelection ${zensecondaryfg},${zenselectionbg} - face PrimaryCursor ${zencursor} - face SecondaryCursor ${zencursor} - face PrimaryCursorEol ${zencursoreol} - face SecondaryCursorEol ${zencursoreol} - face LineNumbers ${zendefault} - face LineNumberCursor ${zenstatus} - face MenuForeground ${zenmenufg} - face MenuBackground ${zenmenubg} - face MenuInfo rgb:cc9393 - face Information ${zeninfo} - face Error default,red - face StatusLine ${zenstatus} - face StatusLineMode ${zencomment} - face StatusLineInfo ${zenspecial} - face StatusLineValue ${zennumber} - face StatusCursor ${zenstatuscursor} - face Prompt ${zenconstant} - face MatchingChar default+b - face BufferPadding ${zenpadding} + face global Default ${zendefault} + face global PrimarySelection ${zentext},${zenselectionbg} + face global SecondarySelection ${zensecondaryfg},${zenselectionbg} + face global PrimaryCursor ${zencursor} + face global SecondaryCursor ${zencursor} + face global PrimaryCursorEol ${zencursoreol} + face global SecondaryCursorEol ${zencursoreol} + face global LineNumbers ${zendefault} + face global LineNumberCursor ${zenstatus} + face global MenuForeground ${zenmenufg} + face global MenuBackground ${zenmenubg} + face global MenuInfo rgb:cc9393 + face global Information ${zeninfo} + face global Error default,red + face global StatusLine ${zenstatus} + face global StatusLineMode ${zencomment} + face global StatusLineInfo ${zenspecial} + face global StatusLineValue ${zennumber} + face global StatusCursor ${zenstatuscursor} + face global Prompt ${zenconstant} + face global MatchingChar default+b + face global BufferPadding ${zenpadding} " } diff --git a/doc/pages/commands.asciidoc b/doc/pages/commands.asciidoc index 4baf5cbf..58cf4e0e 100644 --- a/doc/pages/commands.asciidoc +++ b/doc/pages/commands.asciidoc @@ -161,9 +161,12 @@ command *q!* has to be used). Aliases are mentionned below each commands. *-debug*::: print the given text to the *\*debug** buffer -*set-face* :: +*set-face* :: *alias* face + - define a face (See <>) + define a face in *scope* (See <>) + +*unset-face* :: + Remove a face definition from *scope* (See <>) *colorscheme* :: load named colorscheme diff --git a/rc/base/mercurial.kak b/rc/base/mercurial.kak index c626e883..fabc6d94 100644 --- a/rc/base/mercurial.kak +++ b/rc/base/mercurial.kak @@ -4,7 +4,7 @@ # Faces # ‾‾‾‾‾ -set-face MercurialCommitComment cyan +set-face global MercurialCommitComment cyan # Detection # ‾‾‾‾‾‾‾‾‾ diff --git a/rc/core/kakrc.kak b/rc/core/kakrc.kak index 9eb773a2..da84075a 100644 --- a/rc/core/kakrc.kak +++ b/rc/core/kakrc.kak @@ -30,8 +30,8 @@ add-highlighter shared/ regions -default code kakrc \ buffer buffer-next buffer-previous delete-buffer add-highlighter remove-highlighter hook remove-hooks define-command echo debug source try fail set-option unset-option update-option declare-option execute-keys evaluate-commands - prompt menu on-key info set-face rename-client set-register select change-directory - rename-session colorscheme declare-user-mode enter-user-mode" + prompt menu on-key info set-face unset-face rename-client set-register select + change-directory rename-session colorscheme declare-user-mode enter-user-mode" attributes="global buffer window current normal insert menu prompt goto view user object number_lines show_matching show_whitespaces fill regex dynregex group flag_lines diff --git a/rc/extra/git-tools.kak b/rc/extra/git-tools.kak index 8f5d1c42..46315318 100644 --- a/rc/extra/git-tools.kak +++ b/rc/extra/git-tools.kak @@ -20,8 +20,8 @@ hook -group git-status-highlight global WinSetOption filetype=(?!git-status).* % declare-option -hidden line-specs git_blame_flags declare-option -hidden line-specs git_diff_flags -set-face GitBlame default,magenta -set-face GitDiffFlags default,black +set-face global GitBlame default,magenta +set-face global GitDiffFlags default,black define-command -params 1.. \ -docstring %sh{printf '%%{git []: git wrapping helper diff --git a/src/alias_registry.hh b/src/alias_registry.hh index 952669a0..c35cdf70 100644 --- a/src/alias_registry.hh +++ b/src/alias_registry.hh @@ -33,7 +33,7 @@ public: private: friend class Scope; - AliasRegistry() {} + AliasRegistry() = default; SafePtr m_parent; using AliasMap = HashMap; diff --git a/src/client.cc b/src/client.cc index 6520dc9c..22836a25 100644 --- a/src/client.cc +++ b/src/client.cc @@ -96,7 +96,8 @@ bool Client::process_pending_inputs() catch (Kakoune::runtime_error& error) { write_to_debug_buffer(format("Error: {}", error.what())); - context().print_status({ fix_atom_text(error.what().str()), get_face("Error") }); + context().print_status({ fix_atom_text(error.what().str()), + context().faces()["Error"] }); context().hooks().run_hook("RuntimeError", error.what(), context()); } } @@ -142,15 +143,16 @@ DisplayLine Client::generate_mode_line() const { const String& modelinefmt = context().options()["modelinefmt"].get(); HashMap atoms{{ "mode_info", context().client().input_handler().mode_line() }, - { "context_info", {generate_context_info(context()), get_face("Information")}}}; + { "context_info", {generate_context_info(context()), + context().faces()["Information"]}}}; auto expanded = expand(modelinefmt, context(), ShellContext{}, [](String s) { return escape(s, '{', '\\'); }); - modeline = parse_display_line(expanded, atoms); + modeline = parse_display_line(expanded, context().faces(), atoms); } catch (runtime_error& err) { write_to_debug_buffer(format("Error while parsing modelinefmt: {}", err.what())); - modeline.push_back({ "modelinefmt error, see *debug* buffer", get_face("Error") }); + modeline.push_back({ "modelinefmt error, see *debug* buffer", context().faces()["Error"] }); } return modeline; @@ -207,9 +209,11 @@ void Client::redraw_ifn() if (m_ui_pending == 0) return; + auto& faces = context().faces(); + if (m_ui_pending & Draw) m_ui->draw(window.update_display_buffer(context()), - get_face("Default"), get_face("BufferPadding")); + faces["Default"], faces["BufferPadding"]); const bool update_menu_anchor = (m_ui_pending & Draw) and not (m_ui_pending & MenuHide) and not m_menu.items.empty() and m_menu.style == MenuStyle::Inline; @@ -224,7 +228,7 @@ void Client::redraw_ifn() if (m_ui_pending & MenuShow and m_menu.ui_anchor) m_ui->menu_show(m_menu.items, *m_menu.ui_anchor, - get_face("MenuForeground"), get_face("MenuBackground"), + faces["MenuForeground"], faces["MenuBackground"], m_menu.style); if (m_ui_pending & MenuSelect and m_menu.ui_anchor) m_ui->menu_select(m_menu.selected); @@ -244,12 +248,12 @@ void Client::redraw_ifn() if (m_ui_pending & InfoShow and m_info.ui_anchor) m_ui->info_show(m_info.title, m_info.content, *m_info.ui_anchor, - get_face("Information"), m_info.style); + faces["Information"], m_info.style); if (m_ui_pending & InfoHide) m_ui->info_hide(); if (m_ui_pending & StatusLine) - m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine")); + m_ui->draw_status(m_status_line, m_mode_line, faces["StatusLine"]); auto cursor = m_input_handler.get_cursor_info(); m_ui->set_cursor(cursor.first, cursor.second); @@ -272,12 +276,12 @@ void Client::reload_buffer() { reload_file_buffer(buffer); context().print_status({ format("'{}' reloaded", buffer.display_name()), - get_face("Information") }); + context().faces()["Information"] }); } catch (runtime_error& error) { context().print_status({ format("error while reloading buffer: '{}'", error.what()), - get_face("Error") }); + context().faces()["Error"] }); buffer.set_fs_timestamp(get_fs_timestamp(buffer.name())); } } @@ -305,14 +309,14 @@ void Client::on_buffer_reload_key(Key key) // reread timestamp in case the file was modified again buffer.set_fs_timestamp(get_fs_timestamp(buffer.name())); print_status({ format("'{}' kept", buffer.display_name()), - get_face("Information") }); + context().faces()["Information"] }); if (key == 'N') set_autoreload(Autoreload::No); } else { print_status({ format("'{}' is not a valid choice", key_to_str(key)), - get_face("Error") }); + context().faces()["Error"] }); m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); }); return; } diff --git a/src/client_manager.cc b/src/client_manager.cc index e4e37f0b..b812c958 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -65,7 +65,8 @@ Client* ClientManager::create_client(std::unique_ptr&& ui, int pi } catch (Kakoune::runtime_error& error) { - client->context().print_status({ fix_atom_text(error.what().str()), get_face("Error") }); + client->context().print_status({ fix_atom_text(error.what().str()), + client->context().faces()["Error"] }); client->context().hooks().run_hook("RuntimeError", error.what(), client->context()); } diff --git a/src/commands.cc b/src/commands.cc index b287c652..7d93afb8 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -249,7 +249,7 @@ void edit(const ParametersParser& parser, Context& context, const ShellContext&) : open_or_create_file_buffer(name, flags); if (buffer->flags() & Buffer::Flags::New) context.print_status({ format("new file '{}'", name), - get_face("StatusLine") }); + context.faces()["StatusLine"] }); } buffer->flags() &= ~Buffer::Flags::NoHooks; @@ -1102,9 +1102,9 @@ const CommandDesc echo_cmd = { if (parser.get_switch("debug")) write_to_debug_buffer(message); else if (parser.get_switch("markup")) - context.print_status(parse_display_line(message)); + context.print_status(parse_display_line(message, context.faces())); else - context.print_status({ std::move(message), get_face("StatusLine") }); + context.print_status({ std::move(message), context.faces()["StatusLine"] }); } }; @@ -1192,7 +1192,7 @@ const CommandDesc debug_cmd = { else if (parser[0] == "faces") { write_to_debug_buffer("Faces:"); - for (auto& face : FaceRegistry::instance().aliases()) + for (auto& face : context.faces().flatten_faces()) write_to_debug_buffer(format(" * {}: {}", face.key, face.value.face)); } else if (parser[0] == "mappings") @@ -1809,7 +1809,7 @@ const CommandDesc prompt_cmd = { CapturedShellContext sc{shell_context}; context.input_handler().prompt( - parser[0], initstr.str(), {}, get_face("Prompt"), + parser[0], initstr.str(), {}, context.faces()["Prompt"], flags, std::move(completer), [=](StringView str, PromptEvent event, Context& context) mutable { @@ -1873,7 +1873,7 @@ const CommandDesc menu_cmd = { Vector select_cmds; for (int i = 0; i < count; i += modulo) { - choices.push_back(markup ? parse_display_line(parser[i]) + choices.push_back(markup ? parse_display_line(parser[i], context.faces()) : DisplayLine{ parser[i], {} }); commands.push_back(parser[i+1]); if (with_select_cmds) @@ -1998,17 +1998,18 @@ const CommandDesc try_catch_cmd = { } }; -static Completions complete_face(const Context&, CompletionFlags flags, +static Completions complete_face(const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos) { return {0_byte, cursor_pos, - FaceRegistry::instance().complete_alias_name(prefix, cursor_pos)}; + complete(prefix, cursor_pos, context.faces().flatten_faces() | + transform([](auto& entry) -> const String& { return entry.key; }))}; } const CommandDesc set_face_cmd = { "set-face", "face", - "set-face : set face to refer to \n" + "set-face : set face to refer to in \n" "\n" "facespec format is [,][+]\n" "colors are either a color name, or rgb:###### values.\n" @@ -2016,19 +2017,33 @@ const CommandDesc set_face_cmd = { " u: underline, i: italic, b: bold, r: reverse,\n" " B: blink, d: dim, e: exclusive\n" "facespec can as well just be the name of another face", - ParameterDesc{{}, ParameterDesc::Flags::None, 2, 2}, + ParameterDesc{{}, ParameterDesc::Flags::None, 3, 3}, CommandFlags::None, CommandHelper{}, - make_completer(complete_face, complete_face), + make_completer(complete_scope, complete_face, complete_face), [](const ParametersParser& parser, Context& context, const ShellContext&) { - FaceRegistry::instance().register_alias(parser[0], parser[1], true); + get_scope(parser[0], context).faces().add_face(parser[1], parser[2], true); for (auto& client : ClientManager::instance()) client->force_redraw(); } }; +const CommandDesc unset_face_cmd = { + "unset-face", + nullptr, + "unset-face : remove from ", + ParameterDesc{{}, ParameterDesc::Flags::None, 2, 2}, + CommandFlags::None, + CommandHelper{}, + make_completer(complete_scope, complete_face), + [](const ParametersParser& parser, Context& context, const ShellContext&) + { + get_scope(parser[0], context).faces().remove_face(parser[1]); + } +}; + const CommandDesc rename_client_cmd = { "rename-client", "nc", @@ -2257,6 +2272,7 @@ void register_commands() register_command(info_cmd); register_command(try_catch_cmd); register_command(set_face_cmd); + register_command(unset_face_cmd); register_command(rename_client_cmd); register_command(set_register_cmd); register_command(select_cmd); diff --git a/src/context.cc b/src/context.cc index ece4a2f4..03cf1586 100644 --- a/src/context.cc +++ b/src/context.cc @@ -96,7 +96,7 @@ const SelectionList& JumpList::forward(Context& context, int count) res.update(); context.print_status({ format("jumped to #{} ({})", m_current, m_jumps.size() - 1), - get_face("Information") }); + context.faces()["Information"] }); return res; } throw runtime_error("no next jump"); @@ -117,7 +117,7 @@ const SelectionList& JumpList::backward(Context& context, int count) res.update(); context.print_status({ format("jumped to #{} ({})", m_current, m_jumps.size() - 1), - get_face("Information") }); + context.faces()["Information"] }); return res; } if (m_current != 0) @@ -133,7 +133,7 @@ const SelectionList& JumpList::backward(Context& context, int count) res.update(); context.print_status({ format("jumped to #{} ({})", m_current, m_jumps.size() - 1), - get_face("Information") }); + context.faces()["Information"] }); return res; } throw runtime_error("no previous jump"); diff --git a/src/context.hh b/src/context.hh index cad77d4c..e2903b50 100644 --- a/src/context.hh +++ b/src/context.hh @@ -92,9 +92,10 @@ public: Scope& scope() const; OptionManager& options() const { return scope().options(); } - HookManager& hooks() const { return scope().hooks(); } + HookManager& hooks() const { return scope().hooks(); } KeymapManager& keymaps() const { return scope().keymaps(); } AliasRegistry& aliases() const { return scope().aliases(); } + FaceRegistry& faces() const { return scope().faces(); } void print_status(DisplayLine status) const; diff --git a/src/display_buffer.cc b/src/display_buffer.cc index a634ff5b..20b5588c 100644 --- a/src/display_buffer.cc +++ b/src/display_buffer.cc @@ -3,6 +3,7 @@ #include "assert.hh" #include "buffer.hh" #include "buffer_utils.hh" +#include "face_registry.hh" #include "utf8.hh" #include "face_registry.hh" @@ -241,7 +242,7 @@ void DisplayBuffer::optimize() line.optimize(); } -DisplayLine parse_display_line(StringView line, const HashMap& builtins) +DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const HashMap& builtins) { DisplayLine res; bool was_antislash = false; @@ -278,7 +279,7 @@ DisplayLine parse_display_line(StringView line, const HashMap& builtins = {}); +DisplayLine parse_display_line(StringView line, const FaceRegistry& faces, const HashMap& builtins = {}); class DisplayBuffer : public UseMemoryDomain { diff --git a/src/face_registry.cc b/src/face_registry.cc index 73e4b7b0..880ef6e9 100644 --- a/src/face_registry.cc +++ b/src/face_registry.cc @@ -71,63 +71,62 @@ String to_string(Face face) return format("{},{}{}", face.fg, face.bg, face.attributes); } -Face FaceRegistry::operator[](StringView facedesc) +Face FaceRegistry::operator[](StringView facedesc) const { - auto it = m_aliases.find(facedesc); - while (it != m_aliases.end()) + auto it = m_faces.find(facedesc); + if (it != m_faces.end()) { if (it->value.alias.empty()) return it->value.face; - it = m_aliases.find(it->value.alias); + return operator[](it->value.alias); } + if (m_parent) + return (*m_parent)[facedesc]; return parse_face(facedesc); } -void FaceRegistry::register_alias(StringView name, StringView facedesc, - bool override) +void FaceRegistry::add_face(StringView name, StringView facedesc, bool override) { - if (not override and m_aliases.find(name) != m_aliases.end()) - throw runtime_error(format("alias '{}' already defined", name)); + if (not override and m_faces.find(name) != m_faces.end()) + throw runtime_error(format("face '{}' already defined", name)); if (name.empty() or is_color_name(name) or std::any_of(name.begin(), name.end(), [](char c){ return not isalnum(c); })) - throw runtime_error(format("invalid alias name: '{}'", name)); + throw runtime_error(format("invalid face name: '{}'", name)); if (name == facedesc) throw runtime_error(format("cannot alias face '{}' to itself", name)); - FaceOrAlias& alias = m_aliases[name]; - auto it = m_aliases.find(facedesc); - if (it != m_aliases.end()) + FaceOrAlias& face = m_faces[name]; + auto it = m_faces.find(facedesc); + if (it != m_faces.end()) { - while (it != m_aliases.end()) + while (it != m_faces.end()) { if (it->value.alias.empty()) break; if (it->value.alias == name) throw runtime_error("face cycle detected"); - it = m_aliases.find(it->value.alias); + it = m_faces.find(it->value.alias); } - alias.alias = facedesc.str(); + face.alias = facedesc.str(); } else { - alias.alias = ""; - alias.face = parse_face(facedesc); + face.alias = ""; + face.face = parse_face(facedesc); } } -CandidateList FaceRegistry::complete_alias_name(StringView prefix, - ByteCount cursor_pos) const +void FaceRegistry::remove_face(StringView name) { - return complete(prefix, cursor_pos, - m_aliases | transform(&AliasMap::Item::key)); + m_faces.remove(name); } FaceRegistry::FaceRegistry() - : m_aliases{ + : m_faces{ { "Default", {Face{ Color::Default, Color::Default }} }, { "PrimarySelection", {Face{ Color::White, Color::Blue }} }, { "SecondarySelection", {Face{ Color::Black, Color::Blue }} }, diff --git a/src/face_registry.hh b/src/face_registry.hh index 82006bd2..049227eb 100644 --- a/src/face_registry.hh +++ b/src/face_registry.hh @@ -3,23 +3,35 @@ #include "face.hh" #include "utils.hh" -#include "completion.hh" #include "hash_map.hh" +#include "ranges.hh" +#include "string.hh" +#include "safe_ptr.hh" namespace Kakoune { -class FaceRegistry : public Singleton +class FaceRegistry : public SafeCountable { public: - FaceRegistry(); + FaceRegistry(FaceRegistry& parent) : SafeCountable{}, m_parent(&parent) {} - Face operator[](StringView facedesc); - void register_alias(StringView name, StringView facedesc, - bool override = false); + Face operator[](StringView facedesc) const; + void add_face(StringView name, StringView facedesc, bool override = false); + void remove_face(StringView name); - CandidateList complete_alias_name(StringView prefix, - ByteCount cursor_pos) const; + auto flatten_faces() const + { + auto merge = [](auto&& first, const FaceMap& second) { + return concatenated(std::forward(first) + | filter([&second](auto& i) { return not second.contains(i.key); }), + second); + }; + static const FaceMap empty; + auto& parent = m_parent ? m_parent->m_faces : empty; + auto& grand_parent = (m_parent and m_parent->m_parent) ? m_parent->m_parent->m_faces : empty; + return merge(merge(grand_parent, parent), m_faces); + } struct FaceOrAlias { @@ -27,19 +39,15 @@ public: String alias = {}; }; - using AliasMap = HashMap; - const AliasMap &aliases() const { return m_aliases; } - private: - AliasMap m_aliases; -}; + friend class Scope; + FaceRegistry(); -inline Face get_face(StringView facedesc) -{ - if (FaceRegistry::has_instance()) - return FaceRegistry::instance()[facedesc]; - return Face{}; -} + SafePtr m_parent; + + using FaceMap = HashMap; + FaceMap m_faces; +}; String to_string(Face face); diff --git a/src/highlighter.cc b/src/highlighter.cc new file mode 100644 index 00000000..66759af5 --- /dev/null +++ b/src/highlighter.cc @@ -0,0 +1,55 @@ +#include "highlighter.hh" + +#include "buffer_utils.hh" + +namespace Kakoune +{ + +void Highlighter::highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range) +{ + if (context.pass & m_passes) try + { + do_highlight(context, display_buffer, range); + } + catch (runtime_error& error) + { + write_to_debug_buffer(format("Error while highlighting: {}", error.what())); + } +} + +void Highlighter::compute_display_setup(HighlightContext context, DisplaySetup& setup) const +{ + if (context.pass & m_passes) + do_compute_display_setup(context, setup); +} + + +bool Highlighter::has_children() const +{ + return false; +} + +Highlighter& Highlighter::get_child(StringView path) +{ + throw runtime_error("this highlighter do not hold children"); +} + +void Highlighter::add_child(HighlighterAndId&& hl) +{ + throw runtime_error("this highlighter do not hold children"); +} + +void Highlighter::remove_child(StringView id) +{ + throw runtime_error("this highlighter do not hold children"); +} + +Completions Highlighter::complete_child(StringView path, ByteCount cursor_pos, bool group) const +{ + throw runtime_error("this highlighter do not hold children"); +} + +void Highlighter::fill_unique_ids(Vector& unique_ids) const +{} + +} diff --git a/src/highlighter.hh b/src/highlighter.hh index 122f26ac..f3b7e3fd 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -65,25 +65,15 @@ struct Highlighter Highlighter(HighlightPass passes) : m_passes{passes} {} virtual ~Highlighter() = default; - void highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range) - { - if (context.pass & m_passes) - do_highlight(context, display_buffer, range); - } + void highlight(HighlightContext context, DisplayBuffer& display_buffer, BufferRange range); + void compute_display_setup(HighlightContext context, DisplaySetup& setup) const; - void compute_display_setup(HighlightContext context, DisplaySetup& setup) const - { - if (context.pass & m_passes) - do_compute_display_setup(context, setup); - } - - virtual bool has_children() const { return false; } - virtual Highlighter& get_child(StringView path) { throw runtime_error("this highlighter do not hold children"); } - virtual void add_child(HighlighterAndId&& hl) { throw runtime_error("this highlighter do not hold children"); } - virtual void remove_child(StringView id) { throw runtime_error("this highlighter do not hold children"); } - virtual Completions complete_child(StringView path, ByteCount cursor_pos, bool group) const { throw runtime_error("this highlighter do not hold children"); } - - virtual void fill_unique_ids(Vector& unique_ids) const {} + virtual bool has_children() const; + virtual Highlighter& get_child(StringView path); + virtual void add_child(HighlighterAndId&& hl); + virtual void remove_child(StringView id); + virtual Completions complete_child(StringView path, ByteCount cursor_pos, bool group) const; + virtual void fill_unique_ids(Vector& unique_ids) const; HighlightPass passes() const { return m_passes; } diff --git a/src/highlighters.cc b/src/highlighters.cc index 59a67f1a..323257ab 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -225,12 +225,10 @@ static HighlighterAndId create_fill_highlighter(HighlighterParameters params) throw runtime_error("wrong parameter count"); const String& facespec = params[0]; - get_face(facespec); // validate param - - auto func = [=](HighlightContext, DisplayBuffer& display_buffer, BufferRange range) + auto func = [facespec](HighlightContext context, DisplayBuffer& display_buffer, BufferRange range) { highlight_range(display_buffer, range.begin, range.end, false, - apply_face(get_face(facespec))); + apply_face(context.context.faces()[facespec])); }; return {"fill_" + facespec, make_highlighter(std::move(func))}; } @@ -278,7 +276,7 @@ public: for (int f = 0; f < m_faces.size(); ++f) { if (not m_faces[f].second.empty()) - faces[f] = get_face(m_faces[f].second); + faces[f] = context.context.faces()[m_faces[f].second]; } auto& matches = get_matches(context.context.buffer(), display_buffer.range(), range); @@ -314,7 +312,6 @@ public: auto colon = find(spec, ':'); if (colon == spec.end()) throw runtime_error(format("wrong face spec: '{}' expected :", spec)); - get_face({colon+1, spec.end()}); // throw if wrong face spec int capture = str_to_int({spec.begin(), colon}); faces.emplace_back(capture, String{colon+1, spec.end()}); } @@ -495,7 +492,6 @@ HighlighterAndId create_dynamic_regex_highlighter(HighlighterParameters params) if (colon == spec.end()) throw runtime_error("wrong face spec: '" + spec + "' expected :"); - get_face({colon+1, spec.end()}); // throw if wrong face spec int capture = str_to_int({spec.begin(), colon}); faces.emplace_back(capture, String{colon+1, spec.end()}); } @@ -539,12 +535,8 @@ HighlighterAndId create_line_highlighter(HighlighterParameters params) if (params.size() != 2) throw runtime_error("wrong parameter count"); - String facespec = params[1]; - String line_expr = params[0]; - - get_face(facespec); // validate facespec - - auto func = [=](HighlightContext context, DisplayBuffer& display_buffer, BufferRange) + auto func = [line_expr=params[0], facespec=params[1]] + (HighlightContext context, DisplayBuffer& display_buffer, BufferRange) { LineCount line = -1; try @@ -566,7 +558,7 @@ HighlighterAndId create_line_highlighter(HighlighterParameters params) if (it == display_buffer.lines().end()) return; - auto face = get_face(facespec); + auto face = context.context.faces()[facespec]; ColumnCount column = 0; for (auto& atom : *it) { @@ -590,12 +582,8 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params) if (params.size() != 2) throw runtime_error("wrong parameter count"); - String facespec = params[1]; - String col_expr = params[0]; - - get_face(facespec); // validate facespec - - auto func = [=](HighlightContext context, DisplayBuffer& display_buffer, BufferRange) + auto func = [col_expr=params[0], facespec=params[1]] + (HighlightContext context, DisplayBuffer& display_buffer, BufferRange) { ColumnCount column = -1; try @@ -611,7 +599,7 @@ HighlighterAndId create_column_highlighter(HighlighterParameters params) if (column < 0) return; - auto face = get_face(facespec); + auto face = context.context.faces()[facespec]; auto win_column = context.context.window().position().column; for (auto& line : display_buffer.lines()) { @@ -937,7 +925,7 @@ void show_whitespaces(HighlightContext context, DisplayBuffer& display_buffer, B StringView spc, StringView lf, StringView nbsp) { const int tabstop = context.context.options()["tabstop"].get(); - auto whitespaceface = get_face("Whitespace"); + auto whitespaceface = context.context.faces()["Whitespace"]; auto& buffer = context.context.buffer(); auto win_column = context.context.window().position().column; for (auto& line : display_buffer.lines()) @@ -1043,9 +1031,10 @@ private: if (contains(context.disabled_ids, ms_id)) return; - const Face face = get_face("LineNumbers"); - const Face face_wrapped = get_face("LineNumbersWrapped"); - const Face face_absolute = get_face("LineNumberCursor"); + auto& faces = context.context.faces(); + const Face face = faces["LineNumbers"]; + const Face face_wrapped = faces["LineNumbersWrapped"]; + const Face face_absolute = faces["LineNumberCursor"]; int digit_count = compute_digit_count(context.context); char format[16]; @@ -1102,7 +1091,7 @@ constexpr StringView LineNumbersHighlighter::ms_id; void show_matching_char(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) { - const Face face = get_face("MatchingChar"); + const Face face = context.context.faces()["MatchingChar"]; using CodepointPair = std::pair; static const CodepointPair matching_chars[] = { { '(', ')' }, { '{', '}' }, { '[', ']' }, { '<', '>' } }; const auto range = display_buffer.range(); @@ -1162,10 +1151,11 @@ HighlighterAndId create_matching_char_highlighter(HighlighterParameters params) void highlight_selections(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) { const auto& buffer = context.context.buffer(); - const Face faces[6] = { - get_face("PrimarySelection"), get_face("SecondarySelection"), - get_face("PrimaryCursor"), get_face("SecondaryCursor"), - get_face("PrimaryCursorEol"), get_face("SecondaryCursorEol"), + const auto& faces = context.context.faces(); + const Face sel_faces[6] = { + faces["PrimarySelection"], faces["SecondarySelection"], + faces["PrimaryCursor"], faces["SecondaryCursor"], + faces["PrimaryCursorEol"], faces["SecondaryCursorEol"], }; const auto& selections = context.context.selections(); @@ -1178,7 +1168,7 @@ void highlight_selections(HighlightContext context, DisplayBuffer& display_buffe const bool primary = (i == selections.main_index()); highlight_range(display_buffer, begin, end, false, - apply_face(faces[primary ? 0 : 1])); + apply_face(sel_faces[primary ? 0 : 1])); } for (size_t i = 0; i < selections.size(); ++i) { @@ -1187,14 +1177,14 @@ void highlight_selections(HighlightContext context, DisplayBuffer& display_buffe const bool primary = (i == selections.main_index()); const bool eol = buffer[coord.line].length() - 1 == coord.column; highlight_range(display_buffer, coord, buffer.char_next(coord), false, - apply_face(faces[2 + (eol ? 2 : 0) + (primary ? 0 : 1)])); + apply_face(sel_faces[2 + (eol ? 2 : 0) + (primary ? 0 : 1)])); } } void expand_unprintable(HighlightContext context, DisplayBuffer& display_buffer, BufferRange) { auto& buffer = context.context.buffer(); - auto error = get_face("Error"); + auto error = context.context.faces()["Error"]; for (auto& line : display_buffer.lines()) { for (auto atom_it = line.begin(); atom_it != line.end(); ++atom_it) @@ -1281,7 +1271,6 @@ struct FlagLinesHighlighter : Highlighter const String& option_name = params[1]; const String& default_face = params[0]; - get_face(default_face); // validate param // throw if wrong option type GlobalScope::instance().options()[option_name].get(); @@ -1296,14 +1285,14 @@ private: auto& buffer = context.context.buffer(); update_line_specs_ifn(buffer, line_flags); - auto def_face = get_face(m_default_face); + auto def_face = context.context.faces()[m_default_face]; Vector display_lines; auto& lines = line_flags.list; try { for (auto& line : lines) { - display_lines.push_back(parse_display_line(std::get<1>(line))); + display_lines.push_back(parse_display_line(std::get<1>(line), context.context.faces())); for (auto& atom : display_lines.back()) atom.face = merge_faces(def_face, atom.face); } @@ -1350,7 +1339,7 @@ private: try { for (auto& line : line_flags.list) - width = std::max(parse_display_line(std::get<1>(line)).length(), width); + width = std::max(parse_display_line(std::get<1>(line), context.context.faces()).length(), width); } catch (runtime_error& err) { @@ -1471,7 +1460,7 @@ private: auto& r = std::get<0>(range); if (buffer.is_valid(r.first) and (buffer.is_valid(r.last) and not buffer.is_end(r.last))) highlight_range(display_buffer, r.first, buffer.char_next(r.last), false, - apply_face(get_face(std::get<1>(range)))); + apply_face(context.context.faces()[std::get<1>(range)])); } catch (runtime_error&) {} @@ -1513,7 +1502,7 @@ private: auto& r = std::get<0>(range); if (buffer.is_valid(r.first) and buffer.is_valid(r.last)) { - auto replacement = parse_display_line(std::get<1>(range)); + auto replacement = parse_display_line(std::get<1>(range), context.context.faces()); replace_range(display_buffer, r.first, buffer.char_next(r.last), [&](DisplayLine& line, int beg_idx, int end_idx){ auto it = line.erase(line.begin() + beg_idx, line.begin() + end_idx); diff --git a/src/hook_manager.cc b/src/hook_manager.cc index d5238de6..b869c261 100644 --- a/src/hook_manager.cc +++ b/src/hook_manager.cc @@ -133,7 +133,7 @@ void HookManager::run_hook(StringView hook_name, StringView param, Context& cont if (hook_error) context.print_status({ format("Error running hooks for '{}' '{}', see *debug* buffer", - hook_name, param), get_face("Error") }); + hook_name, param), context.faces()["Error"] }); if (profile) { diff --git a/src/input_handler.cc b/src/input_handler.cc index 07909d60..2ee1d40d 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -251,7 +251,7 @@ public: { long long new_val = (long long)m_params.count * 10 + *cp - '0'; if (new_val > std::numeric_limits::max()) - context().print_status({ "parameter overflowed", get_face("Error") }); + context().print_status({ "parameter overflowed", context().faces()["Error"] }); else m_params.count = new_val; } @@ -277,7 +277,7 @@ public: else context.print_status( { format("invalid register '{}'", *cp), - get_face("Error") }); + context.faces()["Error"] }); }, "enter target register", register_doc); } else @@ -319,19 +319,19 @@ public: auto num_sel = context().selections().size(); auto main_index = context().selections().main_index(); if (num_sel == 1) - atoms.emplace_back(format("{} sel", num_sel), get_face("StatusLineInfo")); + atoms.emplace_back(format("{} sel", num_sel), context().faces()["StatusLineInfo"]); else - atoms.emplace_back(format("{} sels ({})", num_sel, main_index + 1), get_face("StatusLineInfo")); + atoms.emplace_back(format("{} sels ({})", num_sel, main_index + 1), context().faces()["StatusLineInfo"]); if (m_params.count != 0) { - atoms.emplace_back(" param=", get_face("StatusLineInfo")); - atoms.emplace_back(to_string(m_params.count), get_face("StatusLineValue")); + atoms.emplace_back(" param=", context().faces()["StatusLineInfo"]); + atoms.emplace_back(to_string(m_params.count), context().faces()["StatusLineValue"]); } if (m_params.reg) { - atoms.emplace_back(" reg=", get_face("StatusLineInfo")); - atoms.emplace_back(StringView(m_params.reg).str(), get_face("StatusLineValue")); + atoms.emplace_back(" reg=", context().faces()["StatusLineInfo"]); + atoms.emplace_back(StringView(m_params.reg).str(), context().faces()["StatusLineValue"]); } return atoms; } @@ -425,6 +425,8 @@ void to_prev_word_begin(CharCount& pos, StringView line) class LineEditor { public: + LineEditor(const FaceRegistry& faces) : m_faces{faces} {} + void handle_key(Key key) { if (key == Key::Left or key == alt('h')) @@ -528,8 +530,8 @@ public: const bool empty = m_line.empty(); StringView str = empty ? m_empty_text : m_line; - const Face line_face = get_face(empty ? "StatusLineInfo" : "StatusLine"); - const Face cursor_face = get_face("StatusCursor"); + const Face line_face = m_faces[empty ? "StatusLineInfo" : "StatusLine"]; + const Face cursor_face = m_faces["StatusCursor"]; if (m_cursor_pos == str.char_length()) return DisplayLine{{ { fix_atom_text(str.substr(m_display_pos, width-1)), line_face }, @@ -545,6 +547,8 @@ private: String m_line; StringView m_empty_text = {}; + + const FaceRegistry& m_faces; }; class Menu : public InputMode @@ -554,7 +558,8 @@ public: MenuCallback callback) : InputMode(input_handler), m_callback(std::move(callback)), m_choices(choices.begin(), choices.end()), - m_selected(m_choices.begin()) + m_selected(m_choices.begin()), + m_filter_editor{context().faces()} { if (not context().has_client()) return; @@ -648,14 +653,14 @@ public: auto prompt = "filter:"_str; auto width = context().client().dimensions().column - prompt.column_length(); auto display_line = m_filter_editor.build_display_line(width); - display_line.insert(display_line.begin(), { prompt, get_face("Prompt") }); + display_line.insert(display_line.begin(), { prompt, context().faces()["Prompt"] }); context().print_status(display_line); } } DisplayLine mode_line() const override { - return { "menu", get_face("StatusLineMode") }; + return { "menu", context().faces()["StatusLineMode"] }; } KeymapMode keymap_mode() const override { return KeymapMode::Menu; } @@ -714,7 +719,8 @@ public: m_line_changed = false; } context().hooks().run_hook("PromptIdle", "", context()); - }} + }}, + m_line_editor{context().faces()} { m_history_it = ms_history[m_prompt].end(); m_line_editor.reset(std::move(initstr), m_empty_text); @@ -884,7 +890,7 @@ public: } catch (std::runtime_error& error) { - context().print_status({error.what(), get_face("Error")}); + context().print_status({error.what(), context().faces()["Error"]}); return; } } @@ -912,7 +918,7 @@ public: DisplayLine mode_line() const override { - return { "prompt", get_face("StatusLineMode") }; + return { "prompt", context().faces()["StatusLineMode"] }; } KeymapMode keymap_mode() const override { return KeymapMode::Prompt; } @@ -1046,7 +1052,7 @@ public: DisplayLine mode_line() const override { - return { "enter key", get_face("StatusLineMode") }; + return { "enter key", context().faces()["StatusLineMode"] }; } KeymapMode keymap_mode() const override { return m_keymap_mode; } @@ -1257,7 +1263,7 @@ public: context().buffer().commit_undo_group(); context().print_status({ format("committed change #{}", context().buffer().current_history_id()), - get_face("Information") }); + context().faces()["Information"] }); } else if (key == ctrl('v')) { @@ -1291,9 +1297,10 @@ public: { auto num_sel = context().selections().size(); auto main_index = context().selections().main_index(); - return {AtomList{ { "insert", get_face("StatusLineMode") }, - { " ", get_face("StatusLine") }, - { format( "{} sels ({})", num_sel, main_index + 1), get_face("StatusLineInfo") } }}; + return {AtomList{ { "insert", context().faces()["StatusLineMode"] }, + { " ", context().faces()["StatusLine"] }, + { format( "{} sels ({})", num_sel, main_index + 1), + context().faces()["StatusLineInfo"] } }}; } KeymapMode keymap_mode() const override { return KeymapMode::Insert; } diff --git a/src/insert_completer.cc b/src/insert_completer.cc index 542a1b8a..1785648c 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -89,7 +89,9 @@ WordDB& get_word_db(const Buffer& buffer) } template -InsertCompletion complete_word(const SelectionList& sels, const OptionManager& options) +InsertCompletion complete_word(const SelectionList& sels, + const OptionManager& options, + const FaceRegistry& faces) { ConstArrayView extra_word_chars = options["extra_word_chars"].get>(); auto is_word_pred = [extra_word_chars](Codepoint c) { return is_word(c, extra_word_chars); }; @@ -190,7 +192,7 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o const auto pad_len = longest + 1 - first->candidate().char_length(); menu_entry.push_back(first->candidate().str()); menu_entry.push_back(String{' ', pad_len}); - menu_entry.push_back({ first->buffer->display_name(), get_face("MenuInfo") }); + menu_entry.push_back({ first->buffer->display_name(), faces["MenuInfo"] }); } else menu_entry.push_back(first->candidate().str()); @@ -205,7 +207,8 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o template InsertCompletion complete_filename(const SelectionList& sels, - const OptionManager& options) + const OptionManager& options, + const FaceRegistry&) { const Buffer& buffer = sels.buffer(); auto pos = buffer.iterator_at(sels.main().cursor()); @@ -268,6 +271,7 @@ InsertCompletion complete_filename(const SelectionList& sels, InsertCompletion complete_option(const SelectionList& sels, const OptionManager& options, + const FaceRegistry& faces, StringView option_name) { const Buffer& buffer = sels.buffer(); @@ -323,7 +327,7 @@ InsertCompletion complete_option(const SelectionList& sels, match.docstring = std::get<1>(candidate); auto& menu = std::get<2>(candidate); match.menu_entry = not menu.empty() ? - parse_display_line(expand_tabs(menu, tabstop, column)) + parse_display_line(expand_tabs(menu, tabstop, column), faces) : DisplayLine{ expand_tabs(menu, tabstop, column) }; matches.push_back(std::move(match)); @@ -353,7 +357,9 @@ InsertCompletion complete_option(const SelectionList& sels, } template -InsertCompletion complete_line(const SelectionList& sels, const OptionManager& options) +InsertCompletion complete_line(const SelectionList& sels, + const OptionManager& options, + const FaceRegistry&) { const Buffer& buffer = sels.buffer(); BufferCoord cursor_pos = sels.main().cursor(); @@ -403,7 +409,7 @@ InsertCompletion complete_line(const SelectionList& sels, const OptionManager& o } InsertCompleter::InsertCompleter(Context& context) - : m_context(context), m_options(context.options()) + : m_context(context), m_options(context.options()), m_faces(context.faces()) { m_options.register_watcher(*this); } @@ -516,8 +522,10 @@ bool InsertCompleter::setup_ifn() try_complete(complete_filename)) return true; if (completer.mode == InsertCompleterDesc::Option and - try_complete([&](const SelectionList& sels, const OptionManager& options) { - return complete_option(sels, options, *completer.param); + try_complete([&](const SelectionList& sels, + const OptionManager& options, + const FaceRegistry& faces) { + return complete_option(sels, options, faces, *completer.param); })) return true; if (completer.mode == InsertCompleterDesc::Word and @@ -583,7 +591,7 @@ bool InsertCompleter::try_complete(Func complete_func) auto& sels = m_context.selections(); try { - m_completions = complete_func(sels, m_options); + m_completions = complete_func(sels, m_options, m_faces); } catch (runtime_error& e) { diff --git a/src/insert_completer.hh b/src/insert_completer.hh index a47a4267..15244bf1 100644 --- a/src/insert_completer.hh +++ b/src/insert_completer.hh @@ -13,6 +13,7 @@ namespace Kakoune struct SelectionList; struct Key; +class FaceRegistry; struct InsertCompleterDesc { @@ -100,12 +101,15 @@ private: void menu_show(); - Context& m_context; - OptionManager& m_options; - InsertCompletion m_completions; - int m_current_candidate = -1; + Context& m_context; + OptionManager& m_options; + const FaceRegistry& m_faces; + InsertCompletion m_completions; + int m_current_candidate = -1; - using CompleteFunc = InsertCompletion (const SelectionList& sels, const OptionManager& options); + using CompleteFunc = InsertCompletion (const SelectionList& sels, + const OptionManager& options, + const FaceRegistry& faces); CompleteFunc* m_explicit_completer = nullptr; }; diff --git a/src/main.cc b/src/main.cc index b7c62aec..8d6b2b67 100644 --- a/src/main.cc +++ b/src/main.cc @@ -50,7 +50,8 @@ static const char* startup_info = " * selections merging behaviour is now a bit more complex again\n" " * 'x' will only jump to next line if full line is already selected\n" " * WORD text object moved to instead of W for consistency\n" -" * rotate main selection moved to ), rotate content to , ( for backward\n"; +" * rotate main selection moved to ), rotate content to , ( for backward\n" +" * faces are now scoped, set-face command takes an additional scope parameter\n"; struct startup_error : runtime_error { @@ -585,7 +586,6 @@ int run_server(StringView session, StringView server_init, RegisterManager register_manager; HighlighterRegistry highlighter_registry; DefinedHighlighters defined_highlighters; - FaceRegistry face_registry; ClientManager client_manager; BufferManager buffer_manager; @@ -667,7 +667,7 @@ int run_server(StringView session, StringView server_init, if (startup_error) local_client->print_status({ "error during startup, see *debug* buffer for details", - get_face("Error") + local_client->context().faces()["Error"] }); if (flags & ServerFlags::StartupInfo) diff --git a/src/normal.cc b/src/normal.cc index b9f9b7f4..4662a23d 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -444,7 +444,7 @@ void command(Context& context, NormalParams params) context.input_handler().prompt( ":", {}, context.main_sel_register_value(':').str(), - get_face("Prompt"), PromptFlags::DropHistoryEntriesWithBlankPrefix, + context.faces()["Prompt"], PromptFlags::DropHistoryEntriesWithBlankPrefix, [](const Context& context, CompletionFlags flags, StringView cmd_line, ByteCount pos) { return CommandManager::instance().complete(context, flags, cmd_line, pos); @@ -456,7 +456,7 @@ void command(Context& context, NormalParams params) if (event == PromptEvent::Change) { auto info = CommandManager::instance().command_info(context, cmdline); - context.input_handler().set_prompt_face(get_face(info ? "Prompt" : "Error")); + context.input_handler().set_prompt_face(context.faces()[info ? "Prompt" : "Error"]); auto autoinfo = context.options()["autoinfo"].get(); if (autoinfo & AutoInfo::Command) @@ -524,7 +524,7 @@ void pipe(Context& context, NormalParams) { const char* prompt = replace ? "pipe:" : "pipe-to:"; context.input_handler().prompt( - prompt, {}, context.main_sel_register_value("|").str(), get_face("Prompt"), + prompt, {}, context.main_sel_register_value("|").str(), context.faces()["Prompt"], PromptFlags::DropHistoryEntriesWithBlankPrefix, shell_complete, [](StringView cmdline, PromptEvent event, Context& context) @@ -599,7 +599,7 @@ void insert_output(Context& context, NormalParams) { const char* prompt = mode == InsertMode::Insert ? "insert-output:" : "append-output:"; context.input_handler().prompt( - prompt, {}, context.main_sel_register_value("|").str(), get_face("Prompt"), + prompt, {}, context.main_sel_register_value("|").str(), context.faces()["Prompt"], PromptFlags::DropHistoryEntriesWithBlankPrefix, shell_complete, [](StringView cmdline, PromptEvent event, Context& context) @@ -628,7 +628,7 @@ void yank(Context& context, NormalParams params) RegisterManager::instance()[reg].set(context, context.selections_content()); context.print_status({ format("yanked {} selections to register {}", context.selections().size(), reg), - get_face("Information") }); + context.faces()["Information"] }); } template @@ -733,7 +733,7 @@ void regex_prompt(Context& context, String prompt, String default_regex, T func) DisplayCoord position = context.has_window() ? context.window().position() : DisplayCoord{}; SelectionList selections = context.selections(); context.input_handler().prompt( - std::move(prompt), {}, default_regex, get_face("Prompt"), + std::move(prompt), {}, default_regex, context.faces()["Prompt"], PromptFlags::None, complete_nothing, [=](StringView str, PromptEvent event, Context& context) mutable { try @@ -749,7 +749,7 @@ void regex_prompt(Context& context, String prompt, String default_regex, T func) if (context.has_window()) context.window().set_position(position); - context.input_handler().set_prompt_face(get_face("Prompt")); + context.input_handler().set_prompt_face(context.faces()["Prompt"]); } if (not incsearch and event == PromptEvent::Change) @@ -766,7 +766,7 @@ void regex_prompt(Context& context, String prompt, String default_regex, T func) if (event == PromptEvent::Validate) throw; else - context.input_handler().set_prompt_face(get_face("Error")); + context.input_handler().set_prompt_face(context.faces()["Error"]); } catch (runtime_error&) { @@ -852,7 +852,7 @@ void search_next(Context& context, NormalParams params) } while (--params.count > 0); if (main_wrapped) - context.print_status({"main selection search wrapped around buffer", get_face("Information")}); + context.print_status({"main selection search wrapped around buffer", context.faces()["Information"]}); } else throw runtime_error("no search pattern"); @@ -877,7 +877,7 @@ void use_selection_as_search_pattern(Context& context, NormalParams params) context.print_status({ format("register '{}' set to '{}'", reg, fix_atom_text(patterns[sels.main_index()])), - get_face("Information") }); + context.faces()["Information"] }); RegisterManager::instance()[reg].set(context, patterns); @@ -1059,7 +1059,7 @@ void keep(Context& context, NormalParams params) void keep_pipe(Context& context, NormalParams) { context.input_handler().prompt( - "keep pipe:", {}, {}, get_face("Prompt"), + "keep pipe:", {}, {}, context.faces()["Prompt"], PromptFlags::DropHistoryEntriesWithBlankPrefix, shell_complete, [](StringView cmdline, PromptEvent event, Context& context) { if (event != PromptEvent::Validate) @@ -1216,7 +1216,7 @@ void select_object(Context& context, NormalParams params) AutoInfo::Command, context); context.input_handler().prompt( - "object desc:", {}, {}, get_face("Prompt"), + "object desc:", {}, {}, context.faces()["Prompt"], PromptFlags::None, complete_nothing, [count,info](StringView cmdline, PromptEvent event, Context& context) { if (event != PromptEvent::Change) @@ -1499,7 +1499,7 @@ void push_selections(Context& context, NormalParams) { context.push_jump(); context.print_status({ format("saved {} selections", context.selections().size()), - get_face("Information") }); + context.faces()["Information"] }); } void align(Context& context, NormalParams) @@ -1813,7 +1813,7 @@ void save_selections(Context& context, NormalParams params) RegisterManager::instance()[reg].set(context, desc); context.print_status({format("{} {} selections to register '{}'", combine ? "Combined" : "Saved", sels.size(), reg), - get_face("Information")}); + context.faces()["Information"]}); }; if (combine and not empty) @@ -1833,7 +1833,7 @@ void restore_selections(Context& context, NormalParams params) context.selections_write_only() = std::move(sels); context.print_status({format("{} {} selections from register '{}'", combine ? "Combined" : "Restored", size, reg), - get_face("Information")}); + context.faces()["Information"]}); }; if (not combine) @@ -1890,7 +1890,7 @@ void move_in_history(Context& context, NormalParams params) context.print_status({ format("moved to change #{} ({})", history_id, max_history_id), - get_face("Information") }); + context.faces()["Information"] }); } else throw runtime_error(format("no such change: #{} ({})", diff --git a/src/scope.hh b/src/scope.hh index c4b52586..b01799ed 100644 --- a/src/scope.hh +++ b/src/scope.hh @@ -2,10 +2,11 @@ #define scope_hh_INCLUDED #include "alias_registry.hh" +#include "face_registry.hh" +#include "highlighter_group.hh" #include "hook_manager.hh" #include "keymap_manager.hh" #include "option_manager.hh" -#include "highlighter_group.hh" #include "utils.hh" namespace Kakoune @@ -19,6 +20,7 @@ public: m_hooks(parent.hooks()), m_keymaps(parent.keymaps()), m_aliases(parent.aliases()), + m_faces(parent.faces()), m_highlighters(parent.highlighters()) {} OptionManager& options() { return m_options; } @@ -29,6 +31,8 @@ public: const KeymapManager& keymaps() const { return m_keymaps; } AliasRegistry& aliases() { return m_aliases; } const AliasRegistry& aliases() const { return m_aliases; } + FaceRegistry& faces() { return m_faces; } + const FaceRegistry& faces() const { return m_faces; } Highlighters& highlighters() { return m_highlighters; } const Highlighters& highlighters() const { return m_highlighters; } @@ -40,6 +44,7 @@ private: HookManager m_hooks; KeymapManager m_keymaps; AliasRegistry m_aliases; + FaceRegistry m_faces; Highlighters m_highlighters; }; diff --git a/src/shell_manager.cc b/src/shell_manager.cc index 2d0744e0..a6d4a954 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -268,7 +268,7 @@ std::pair ShellManager::eval( client.print_status({ format("waiting for shell command to finish ({}s)", duration_cast(wait_duration).count()), - get_face("Information") }); + context.faces()["Information"] }); client.redraw_ifn(); } timer.set_next_date(Clock::now() + wait_timeout);