textbringer 24 → 25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,180 @@
1
+ module Textbringer
2
+ class Theme
3
+ DEFAULT_THEME = "github"
4
+
5
+ class Palette
6
+ def initialize
7
+ @colors = {}
8
+ end
9
+
10
+ def color(name, hex: nil, ansi: nil)
11
+ @colors[name] = { hex: hex, ansi: ansi }
12
+ end
13
+
14
+ def resolve(name, tier)
15
+ c = @colors[name]
16
+ return nil unless c
17
+ tier == :ansi ? c[:ansi] : c[:hex]
18
+ end
19
+ end
20
+
21
+ @@themes = {}
22
+ @@current = nil
23
+ @@background_mode = nil
24
+
25
+ def self.define(name, &block)
26
+ theme = new(name)
27
+ block.call(theme)
28
+ @@themes[name] = theme
29
+ end
30
+
31
+ def self.[](name)
32
+ @@themes[name]
33
+ end
34
+
35
+ def self.current
36
+ @@current
37
+ end
38
+
39
+ def self.load(name)
40
+ user_path = File.expand_path("~/.textbringer/themes/#{name}.rb")
41
+ if File.exist?(user_path)
42
+ Kernel.load(user_path)
43
+ else
44
+ require "textbringer/themes/#{name}"
45
+ end
46
+ theme = @@themes[name]
47
+ raise EditorError, "Theme '#{name}' not found" unless theme
48
+ theme.activate
49
+ end
50
+
51
+ def self.load_default
52
+ return if @@current
53
+ load(DEFAULT_THEME)
54
+ end
55
+
56
+ def self.background_mode
57
+ mode = CONFIG[:background_mode]
58
+ return mode if mode == :dark || mode == :light
59
+ @@background_mode || :dark
60
+ end
61
+
62
+ def self.detect_background
63
+ @@background_mode = detect_background_via_osc11 ||
64
+ detect_background_via_colorfgbg ||
65
+ :dark
66
+ end
67
+
68
+ def self.color_tier
69
+ Window.colors >= 256 ? :hex : :ansi
70
+ end
71
+
72
+ def initialize(name)
73
+ @name = name
74
+ @palettes = {}
75
+ @face_definitions = []
76
+ @default_colors = nil
77
+ end
78
+
79
+ attr_reader :name
80
+
81
+ def palette(mode, &block)
82
+ p = Palette.new
83
+ block.call(p)
84
+ @palettes[mode] = p
85
+ end
86
+
87
+ def face(name, **attrs)
88
+ @face_definitions << [name, attrs]
89
+ end
90
+
91
+ def default_colors(foreground:, background:)
92
+ @default_colors = { foreground: foreground, background: background }
93
+ end
94
+
95
+ def activate
96
+ mode = self.class.background_mode
97
+ tier = self.class.color_tier
98
+ palette = @palettes[mode] || @palettes[:dark] || Palette.new
99
+ @face_definitions.each do |face_name, attrs|
100
+ resolved = {}
101
+ [:foreground, :background].each do |key|
102
+ val = attrs[key]
103
+ if val.is_a?(Symbol)
104
+ color = palette.resolve(val, tier)
105
+ if color
106
+ resolved[key] = color
107
+ else
108
+ raise EditorError,
109
+ "Unknown palette color :#{val} for #{key} in face #{face_name}"
110
+ end
111
+ elsif val.is_a?(String)
112
+ resolved[key] = val
113
+ end
114
+ end
115
+ [:bold, :underline, :reverse, :inherit].each do |key|
116
+ resolved[key] = attrs[key] if attrs.key?(key)
117
+ end
118
+ Face.define(face_name, **resolved)
119
+ end
120
+ @@current = self
121
+ apply_default_colors(palette, tier)
122
+ end
123
+
124
+ private
125
+
126
+ def apply_default_colors(palette, tier)
127
+ if @default_colors
128
+ fg = resolve_default_color(@default_colors[:foreground], palette, tier)
129
+ bg = resolve_default_color(@default_colors[:background], palette, tier)
130
+ else
131
+ fg = "default"
132
+ bg = "default"
133
+ end
134
+ Window.set_default_colors(fg, bg)
135
+ end
136
+
137
+ def resolve_default_color(val, palette, tier)
138
+ if val.is_a?(Symbol)
139
+ color = palette.resolve(val, tier)
140
+ unless color
141
+ raise EditorError,
142
+ "Unknown palette color :#{val} for default_colors"
143
+ end
144
+ color
145
+ else
146
+ val || "default"
147
+ end
148
+ end
149
+
150
+ private_class_method def self.detect_background_via_osc11
151
+ return nil unless $stdin.tty? && $stdout.tty?
152
+ require "io/console"
153
+ $stdin.raw(min: 0, time: 1) do |io|
154
+ $stdout.write("\e]11;?\e\\")
155
+ $stdout.flush
156
+ response = +""
157
+ while (c = io.getc)
158
+ response << c
159
+ break if response.include?("\e\\") || response.include?("\a")
160
+ end
161
+ if response =~ /\e\]11;rgb:([0-9a-f]+)\/([0-9a-f]+)\/([0-9a-f]+)/i
162
+ r = $1[0..1].to_i(16)
163
+ g = $2[0..1].to_i(16)
164
+ b = $3[0..1].to_i(16)
165
+ luminance = 0.299 * r + 0.587 * g + 0.114 * b
166
+ luminance < 128 ? :dark : :light
167
+ end
168
+ end
169
+ rescue
170
+ nil
171
+ end
172
+
173
+ private_class_method def self.detect_background_via_colorfgbg
174
+ colorfgbg = ENV["COLORFGBG"]
175
+ return nil unless colorfgbg
176
+ bg = colorfgbg.split(";").last.to_i
177
+ bg <= 6 || bg == 8 ? :dark : :light
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,105 @@
1
+ # Catppuccin theme for Textbringer
2
+ # Based on https://github.com/catppuccin/nvim
3
+ #
4
+ # Dark variant: Mocha Light variant: Latte
5
+
6
+ Textbringer::Theme.define "catppuccin" do |t|
7
+ t.palette :dark do |p|
8
+ # Catppuccin Mocha base tones
9
+ p.color :text, hex: "#d7d7ff", ansi: "white"
10
+ p.color :subtext1, hex: "#afafd7", ansi: "white"
11
+ p.color :subtext0, hex: "#afafd7", ansi: "white"
12
+ p.color :overlay2, hex: "#8787af", ansi: "white"
13
+ p.color :overlay1, hex: "#8787af", ansi: "white"
14
+ p.color :overlay0, hex: "#767676", ansi: "brightblack"
15
+ p.color :surface2, hex: "#626262", ansi: "brightblack"
16
+ p.color :surface1, hex: "#4e4e4e", ansi: "brightblack"
17
+ p.color :surface0, hex: "#3a3a3a", ansi: "brightblack"
18
+ p.color :base, hex: "#262626", ansi: "black"
19
+ p.color :mantle, hex: "#1c1c1c", ansi: "black"
20
+ p.color :crust, hex: "#121212", ansi: "black"
21
+
22
+ # Catppuccin Mocha accent colors
23
+ p.color :red, hex: "#ff87af", ansi: "red"
24
+ p.color :maroon, hex: "#d7afaf", ansi: "red"
25
+ p.color :peach, hex: "#ffaf87", ansi: "yellow"
26
+ p.color :yellow, hex: "#ffd7af", ansi: "yellow"
27
+ p.color :green, hex: "#afd7af", ansi: "green"
28
+ p.color :teal, hex: "#87d7d7", ansi: "cyan"
29
+ p.color :sky, hex: "#87d7d7", ansi: "cyan"
30
+ p.color :sapphire, hex: "#87d7ff", ansi: "cyan"
31
+ p.color :blue, hex: "#87afff", ansi: "blue"
32
+ p.color :lavender, hex: "#afafff", ansi: "blue"
33
+ p.color :mauve, hex: "#d7afff", ansi: "magenta"
34
+ p.color :pink, hex: "#ffafd7", ansi: "magenta"
35
+ p.color :flamingo, hex: "#ffd7d7", ansi: "red"
36
+ p.color :rosewater, hex: "#ffd7d7", ansi: "red"
37
+ end
38
+
39
+ t.palette :light do |p|
40
+ # Catppuccin Latte base tones
41
+ p.color :text, hex: "#585858", ansi: "black"
42
+ p.color :subtext1, hex: "#5f5f87", ansi: "black"
43
+ p.color :subtext0, hex: "#767676", ansi: "brightblack"
44
+ p.color :overlay2, hex: "#878787", ansi: "brightblack"
45
+ p.color :overlay1, hex: "#949494", ansi: "white"
46
+ p.color :overlay0, hex: "#a8a8a8", ansi: "white"
47
+ p.color :surface2, hex: "#b2b2b2", ansi: "white"
48
+ p.color :surface1, hex: "#c6c6c6", ansi: "white"
49
+ p.color :surface0, hex: "#d0d0d0", ansi: "white"
50
+ p.color :base, hex: "#eeeeee", ansi: "white"
51
+ p.color :mantle, hex: "#eeeeee", ansi: "white"
52
+ p.color :crust, hex: "#e4e4e4", ansi: "white"
53
+
54
+ # Catppuccin Latte accent colors
55
+ p.color :red, hex: "#d7005f", ansi: "red"
56
+ p.color :maroon, hex: "#d75f5f", ansi: "red"
57
+ p.color :peach, hex: "#ff5f00", ansi: "red"
58
+ p.color :yellow, hex: "#d78700", ansi: "yellow"
59
+ p.color :green, hex: "#5faf00", ansi: "green"
60
+ p.color :teal, hex: "#008787", ansi: "cyan"
61
+ p.color :sky, hex: "#00afd7", ansi: "cyan"
62
+ p.color :sapphire, hex: "#00afaf", ansi: "cyan"
63
+ p.color :blue, hex: "#005fff", ansi: "blue"
64
+ p.color :lavender, hex: "#5f87ff", ansi: "blue"
65
+ p.color :mauve, hex: "#875fff", ansi: "magenta"
66
+ p.color :pink, hex: "#d787d7", ansi: "magenta"
67
+ p.color :flamingo, hex: "#d78787", ansi: "red"
68
+ p.color :rosewater, hex: "#d78787", ansi: "red"
69
+ end
70
+
71
+ t.default_colors foreground: :text, background: :base
72
+
73
+ # Programming faces (from catppuccin/nvim syntax.lua)
74
+ t.face :comment, foreground: :overlay2
75
+ t.face :preprocessing_directive, foreground: :pink
76
+ t.face :keyword, foreground: :mauve
77
+ t.face :string, foreground: :green
78
+ t.face :number, foreground: :peach
79
+ t.face :constant, foreground: :peach
80
+ t.face :function_name, foreground: :blue
81
+ t.face :type, foreground: :yellow
82
+ t.face :variable, foreground: :flamingo
83
+ t.face :operator, foreground: :sky
84
+ t.face :punctuation
85
+ t.face :builtin, foreground: :red
86
+ t.face :property, foreground: :lavender
87
+
88
+ # Basic faces (from catppuccin/nvim editor.lua)
89
+ t.face :mode_line, foreground: :text, background: :mantle
90
+ t.face :link, foreground: :blue, underline: true
91
+ t.face :control
92
+ t.face :region, background: :surface1
93
+ t.face :isearch, foreground: :mantle, background: :red
94
+ t.face :floating_window, foreground: :text, background: :mantle
95
+
96
+ # Completion faces
97
+ t.face :completion_popup, foreground: :overlay2, background: :mantle
98
+ t.face :completion_popup_selected, background: :surface0
99
+
100
+ # Dired faces
101
+ t.face :dired_directory, foreground: :blue
102
+ t.face :dired_symlink, foreground: :teal
103
+ t.face :dired_executable, foreground: :green
104
+ t.face :dired_flagged, foreground: :red
105
+ end
@@ -0,0 +1,89 @@
1
+ # GitHub theme for Textbringer
2
+ # Based on https://github.com/cormacrelf/vim-colors-github
3
+ # Inspired by GitHub's syntax highlighting as of 2018.
4
+ #
5
+ # Light palette: cterm values from source (accurate).
6
+ # Dark palette: GUI hex values — dark-mode cterm values in source are unreliable
7
+ # (e.g. dcolors.blue has cterm=167 which maps to red, overlay has cterm=123
8
+ # which maps to bright cyan).
9
+
10
+ Textbringer::Theme.define "github" do |t|
11
+ t.palette :light do |p|
12
+ # Backgrounds / foreground
13
+ p.color :bg, hex: "#ffffff", ansi: "white" # 231 Normal bg
14
+ p.color :bg1, hex: "#eeeeee", ansi: "white" # 255 overlay/gutter/panels
15
+ p.color :vis, hex: "#afd7ff", ansi: "blue" # 153 Visual selection bg (blue2)
16
+ p.color :search, hex: "#ffffd7", ansi: "yellow" # 230 Search bg (yellow)
17
+ p.color :fg, hex: "#262626", ansi: "black" # 235 Normal fg (base0)
18
+ p.color :comment, hex: "#767676", ansi: "brightblack" # 243 Comment (base2)
19
+ p.color :line_nr, hex: "#bcbcbc", ansi: "white" # 250 LineNr fg (base4)
20
+
21
+ # Syntax colors
22
+ p.color :red, hex: "#d75f5f", ansi: "red" # 167 Statement, Type, PreProc
23
+ p.color :darkred, hex: "#af0000", ansi: "red" # 124 darkred
24
+ p.color :purple, hex: "#8700af", ansi: "magenta" # 91 Function, Define, Special
25
+ p.color :green, hex: "#00875f", ansi: "green" # 29 html/xml tags
26
+ p.color :orange, hex: "#d75f00", ansi: "yellow" # 166 orange
27
+ p.color :blue, hex: "#005fd7", ansi: "blue" # 26 Identifier, Constant, Macro
28
+ p.color :darkblue, hex: "#00005f", ansi: "blue" # 17 String
29
+ end
30
+
31
+ t.palette :dark do |p|
32
+ # Backgrounds / foreground (GUI hex — cterm values are unreliable in source)
33
+ p.color :bg, hex: "#24292e", ansi: "black" # base0 (Normal bg)
34
+ p.color :bg1, hex: "#353a3f", ansi: "brightblack" # dcolors.overlay (panels/popups)
35
+ p.color :vis, hex: "#354a60", ansi: "blue" # dcolors.blue2 / blues[4]
36
+ p.color :search, hex: "#595322", ansi: "yellow" # dcolors.yellow (Search bg)
37
+ p.color :fg, hex: "#fafbfc", ansi: "white" # fafbfc (Normal fg)
38
+ p.color :comment, hex: "#abaeb1", ansi: "brightblack" # darktext[2] (Comment)
39
+ p.color :line_nr, hex: "#76787b", ansi: "brightblack" # numDarkest (base4 in dark)
40
+
41
+ # Syntax colors (GUI hex)
42
+ p.color :red, hex: "#f16636", ansi: "red" # dcolors.red
43
+ p.color :darkred, hex: "#b31d28", ansi: "red" # s:colors.darkred (same both modes)
44
+ p.color :purple, hex: "#a887e6", ansi: "magenta" # dcolors.purple
45
+ p.color :green, hex: "#59b36f", ansi: "green" # dcolors.green
46
+ p.color :orange, hex: "#ffa657", ansi: "yellow" # s:colors.orange (same both modes)
47
+ p.color :blue, hex: "#4dacfd", ansi: "blue" # dcolors.blue
48
+ p.color :darkblue, hex: "#c1daec", ansi: "blue" # dcolors.darkblue = blue1
49
+ end
50
+
51
+ t.default_colors foreground: :fg, background: :bg
52
+
53
+ # Programming faces
54
+ t.face :comment, foreground: :comment # Comment = base2
55
+ t.face :preprocessing_directive, foreground: :red # PreProc = red
56
+ t.face :keyword, foreground: :red # Statement = red
57
+ t.face :string, foreground: :darkblue # String = darkblue
58
+ t.face :number, foreground: :blue # Number → Constant = blue
59
+ t.face :constant, foreground: :blue # Constant = blue
60
+ t.face :function_name, foreground: :purple # Function = purple
61
+ t.face :type, foreground: :orange # Type = orange
62
+ t.face :variable, foreground: :blue # Identifier = blue
63
+ t.face :operator # no explicit color in source
64
+ t.face :punctuation # Delimiter = fg (ghNormalNoBg)
65
+ t.face :builtin, foreground: :purple # Special = purple
66
+ t.face :property, foreground: :blue # Identifier = blue
67
+
68
+ # Basic faces
69
+ # StatusLine: fg=grey2 (~bg1), bg=base0 (~fg) — inverted from Normal in both modes
70
+ t.face :mode_line, foreground: :bg1, background: :fg
71
+ t.face :link, foreground: :blue, underline: true
72
+ t.face :control
73
+ t.face :region, background: :vis # Visual = visualblue
74
+ # Search has no explicit fg in source; fg inherits from Normal
75
+ t.face :isearch, foreground: :fg, background: :search
76
+ t.face :floating_window, foreground: :fg, background: :bg1
77
+
78
+ # Completion faces
79
+ # Pmenu: fg=base3 (≈ comment), bg=overlay (≈ bg1)
80
+ # PmenuSel: fg=overlay (≈ bg1), bg=blue; bold
81
+ t.face :completion_popup, foreground: :comment, background: :bg1
82
+ t.face :completion_popup_selected, foreground: :bg1, background: :blue, bold: true
83
+
84
+ # Dired faces
85
+ t.face :dired_directory, foreground: :blue # Directory → ghBlue
86
+ t.face :dired_symlink, foreground: :darkblue
87
+ t.face :dired_executable, foreground: :green
88
+ t.face :dired_flagged, foreground: :red
89
+ end
@@ -0,0 +1,84 @@
1
+ # Gruvbox theme for Textbringer
2
+ # Based on https://github.com/morhetz/gruvbox
3
+ #
4
+ # Dark: bright accent colors on warm dark background
5
+ # Light: neutral accent colors on warm light background
6
+
7
+ Textbringer::Theme.define "gruvbox" do |t|
8
+ t.palette :dark do |p|
9
+ # Base tones (dark background, light foreground)
10
+ p.color :bg0, hex: "#262626", ansi: "black"
11
+ p.color :bg1, hex: "#3a3a3a", ansi: "brightblack"
12
+ p.color :bg2, hex: "#4e4e4e", ansi: "brightblack"
13
+ p.color :bg3, hex: "#626262", ansi: "brightblack"
14
+ p.color :bg4, hex: "#767676", ansi: "white"
15
+ p.color :fg1, hex: "#ffd7af", ansi: "white"
16
+ p.color :fg4, hex: "#949494", ansi: "white"
17
+ p.color :gray, hex: "#8a8a8a", ansi: "white"
18
+
19
+ # Bright accent colors
20
+ p.color :red, hex: "#d75f5f", ansi: "red"
21
+ p.color :green, hex: "#afaf00", ansi: "green"
22
+ p.color :yellow, hex: "#ffaf00", ansi: "yellow"
23
+ p.color :blue, hex: "#87afaf", ansi: "blue"
24
+ p.color :purple, hex: "#d787af", ansi: "magenta"
25
+ p.color :aqua, hex: "#87af87", ansi: "cyan"
26
+ p.color :orange, hex: "#ff8700", ansi: "yellow"
27
+ end
28
+
29
+ t.palette :light do |p|
30
+ # Base tones (light background, dark foreground)
31
+ p.color :bg0, hex: "#ffffaf", ansi: "white"
32
+ p.color :bg1, hex: "#ffd7af", ansi: "white"
33
+ p.color :bg2, hex: "#bcbcbc", ansi: "white"
34
+ p.color :bg3, hex: "#a8a8a8", ansi: "white"
35
+ p.color :bg4, hex: "#949494", ansi: "brightblack"
36
+ p.color :fg1, hex: "#3a3a3a", ansi: "black"
37
+ p.color :fg4, hex: "#767676", ansi: "brightblack"
38
+ p.color :gray, hex: "#8a8a8a", ansi: "brightblack"
39
+
40
+ # Neutral accent colors
41
+ p.color :red, hex: "#af0000", ansi: "red"
42
+ p.color :green, hex: "#87af00", ansi: "green"
43
+ p.color :yellow, hex: "#d78700", ansi: "yellow"
44
+ p.color :blue, hex: "#5f8787", ansi: "blue"
45
+ p.color :purple, hex: "#af5f87", ansi: "magenta"
46
+ p.color :aqua, hex: "#5faf87", ansi: "cyan"
47
+ p.color :orange, hex: "#d75f00", ansi: "red"
48
+ end
49
+
50
+ t.default_colors foreground: :fg1, background: :bg0
51
+
52
+ # Programming faces
53
+ t.face :comment, foreground: :gray
54
+ t.face :preprocessing_directive, foreground: :aqua
55
+ t.face :keyword, foreground: :red
56
+ t.face :string, foreground: :green
57
+ t.face :number, foreground: :purple
58
+ t.face :constant, foreground: :purple
59
+ t.face :function_name, foreground: :green
60
+ t.face :type, foreground: :yellow
61
+ t.face :variable, foreground: :blue
62
+ t.face :operator
63
+ t.face :punctuation
64
+ t.face :builtin, foreground: :orange
65
+ t.face :property, foreground: :blue
66
+
67
+ # Basic faces
68
+ t.face :mode_line, foreground: :bg2, background: :fg1, reverse: true
69
+ t.face :link, foreground: :blue, underline: true
70
+ t.face :control
71
+ t.face :region, background: :bg3
72
+ t.face :isearch, foreground: :yellow, background: :bg0, reverse: true
73
+ t.face :floating_window, foreground: :fg1, background: :bg1
74
+
75
+ # Completion faces
76
+ t.face :completion_popup, foreground: :fg1, background: :bg2
77
+ t.face :completion_popup_selected, foreground: :bg2, background: :blue, bold: true
78
+
79
+ # Dired faces
80
+ t.face :dired_directory, foreground: :green, bold: true
81
+ t.face :dired_symlink, foreground: :aqua
82
+ t.face :dired_executable, foreground: :green
83
+ t.face :dired_flagged, foreground: :red
84
+ end
@@ -0,0 +1,67 @@
1
+ # Molokai theme for Textbringer
2
+ # Based on https://github.com/tomasr/molokai
3
+ # Original Monokai theme by Wimer Hazenberg; darker variant by Hamish Stuart Macpherson
4
+ #
5
+ # Colors derived from molokai's 256-color (cterm) values.
6
+ # Dark only.
7
+
8
+ Textbringer::Theme.define "molokai" do |t|
9
+ t.palette :dark do |p|
10
+ # Background / foreground (cterm numbers in comments)
11
+ p.color :bg, hex: "#121212", ansi: "black" # 233 Normal bg
12
+ p.color :bg1, hex: "#262626", ansi: "brightblack" # 235 Visual, region
13
+ p.color :bg2, hex: "#303030", ansi: "brightblack" # 236 LineNr bg, floating windows
14
+ p.color :fg, hex: "#d0d0d0", ansi: "white" # 252 Normal fg
15
+ p.color :comment, hex: "#5f5f5f", ansi: "brightblack" # 59 Comment
16
+ p.color :gray, hex: "#444444", ansi: "brightblack" # 238 StatusLine fg
17
+ p.color :silver, hex: "#dadada", ansi: "white" # 253 StatusLine bg
18
+ p.color :mid_gray, hex: "#6c6c6c", ansi: "brightblack" # 242 PmenuSel bg
19
+
20
+ # Accent colors
21
+ p.color :pink, hex: "#d7005f", ansi: "red" # 161 Keyword, Operator
22
+ p.color :green, hex: "#87ff00", ansi: "green" # 118 Function, PreProc
23
+ p.color :yellow, hex: "#afaf87", ansi: "yellow" # 144 String, Character
24
+ p.color :purple, hex: "#af5fff", ansi: "magenta" # 135 Number, Boolean, Constant
25
+ p.color :orange, hex: "#ff8700", ansi: "yellow" # 208 Identifier, StorageClass
26
+ p.color :cyan, hex: "#5fd7ff", ansi: "cyan" # 81 Type, Define, Structure
27
+ p.color :search, hex: "#ffd787", ansi: "yellow" # 222 Search bg
28
+ end
29
+
30
+ t.default_colors foreground: :fg, background: :bg
31
+
32
+ # Programming faces
33
+ t.face :comment, foreground: :comment
34
+ t.face :preprocessing_directive, foreground: :green
35
+ t.face :keyword, foreground: :pink, bold: true
36
+ t.face :string, foreground: :yellow
37
+ t.face :number, foreground: :purple
38
+ t.face :constant, foreground: :purple, bold: true
39
+ t.face :function_name, foreground: :green
40
+ t.face :type, foreground: :cyan
41
+ t.face :variable, foreground: :orange
42
+ t.face :operator, foreground: :pink
43
+ t.face :punctuation
44
+ t.face :builtin, foreground: :cyan
45
+ t.face :property, foreground: :orange
46
+
47
+ # Basic faces
48
+ # StatusLine: ctermfg=238 (#444444) on ctermbg=253 (#DADADA)
49
+ t.face :mode_line, foreground: :gray, background: :silver
50
+ t.face :link, foreground: :cyan, underline: true
51
+ t.face :control
52
+ t.face :region, background: :bg1
53
+ # Search: ctermfg=0 ctermbg=222
54
+ t.face :isearch, foreground: :bg, background: :search
55
+ t.face :floating_window, foreground: :fg, background: :bg2
56
+
57
+ # Completion faces
58
+ # Pmenu: ctermfg=81 ctermbg=16; PmenuSel: ctermfg=252 ctermbg=242
59
+ t.face :completion_popup, foreground: :cyan, background: :bg
60
+ t.face :completion_popup_selected, foreground: :fg, background: :mid_gray
61
+
62
+ # Dired faces
63
+ t.face :dired_directory, foreground: :green, bold: true
64
+ t.face :dired_symlink, foreground: :cyan
65
+ t.face :dired_executable, foreground: :green
66
+ t.face :dired_flagged, foreground: :pink
67
+ end
@@ -0,0 +1,63 @@
1
+ # Sonokai theme for Textbringer (default style)
2
+ # Based on https://github.com/sainnhe/sonokai
3
+ #
4
+ # A dark theme only. Falls back to dark palette on light terminals.
5
+
6
+ Textbringer::Theme.define "sonokai" do |t|
7
+ t.palette :dark do |p|
8
+ # Base tones
9
+ p.color :black, hex: "#080808", ansi: "black"
10
+ p.color :bg_dim, hex: "#080808", ansi: "black"
11
+ p.color :bg0, hex: "#262626", ansi: "black"
12
+ p.color :bg1, hex: "#303030", ansi: "brightblack"
13
+ p.color :bg2, hex: "#303030", ansi: "brightblack"
14
+ p.color :bg3, hex: "#3a3a3a", ansi: "brightblack"
15
+ p.color :bg4, hex: "#3a3a3a", ansi: "brightblack"
16
+ p.color :fg, hex: "#bcbcbc", ansi: "white"
17
+ p.color :grey, hex: "#949494", ansi: "white"
18
+ p.color :grey_dim, hex: "#585858", ansi: "brightblack"
19
+
20
+ # Accent colors
21
+ p.color :red, hex: "#ff5f5f", ansi: "red"
22
+ p.color :orange, hex: "#ffaf5f", ansi: "yellow"
23
+ p.color :yellow, hex: "#d7af5f", ansi: "yellow"
24
+ p.color :green, hex: "#87af5f", ansi: "green"
25
+ p.color :blue, hex: "#87afd7", ansi: "cyan"
26
+ p.color :purple, hex: "#d787d7", ansi: "magenta"
27
+ end
28
+
29
+ t.default_colors foreground: :fg, background: :bg0
30
+
31
+ # Programming faces (from sonokai highlight groups)
32
+ t.face :comment, foreground: :grey
33
+ t.face :preprocessing_directive, foreground: :red
34
+ t.face :keyword, foreground: :red
35
+ t.face :string, foreground: :yellow
36
+ t.face :number, foreground: :purple
37
+ t.face :constant, foreground: :orange
38
+ t.face :function_name, foreground: :green
39
+ t.face :type, foreground: :blue
40
+ t.face :variable, foreground: :orange
41
+ t.face :operator, foreground: :red
42
+ t.face :punctuation
43
+ t.face :builtin, foreground: :green
44
+ t.face :property, foreground: :blue
45
+
46
+ # Basic faces
47
+ t.face :mode_line, foreground: :fg, background: :bg3
48
+ t.face :link, foreground: :blue, underline: true
49
+ t.face :control
50
+ t.face :region, background: :bg4
51
+ t.face :isearch, foreground: :bg0, background: :green
52
+ t.face :floating_window, foreground: :fg, background: :bg_dim
53
+
54
+ # Completion faces
55
+ t.face :completion_popup, foreground: :fg, background: :bg2
56
+ t.face :completion_popup_selected, foreground: :bg0, background: :blue
57
+
58
+ # Dired faces
59
+ t.face :dired_directory, foreground: :green
60
+ t.face :dired_symlink, foreground: :blue
61
+ t.face :dired_executable, foreground: :green
62
+ t.face :dired_flagged, foreground: :red
63
+ end
@@ -0,0 +1,70 @@
1
+ # Tokyo Night theme for Textbringer
2
+ # Based on https://github.com/folke/tokyonight.nvim
3
+ # Night variant (dark only). GUI hex colors — no cterm values in source.
4
+ # Computed colors derived from tokyonight's blend formulas.
5
+
6
+ Textbringer::Theme.define "tokyonight" do |t|
7
+ t.palette :dark do |p|
8
+ # Background / foreground (night variant)
9
+ p.color :bg, hex: "#1a1b26", ansi: "black" # bg
10
+ p.color :bg_dark, hex: "#16161e", ansi: "black" # bg_dark → popups, statusline
11
+ p.color :bg_hl, hex: "#292e42", ansi: "brightblack" # bg_highlight → floating windows
12
+ p.color :bg_vis, hex: "#283457", ansi: "brightblack" # bg_visual = blend(blue0, 0.4, bg)
13
+ p.color :sel_bg, hex: "#343a55", ansi: "brightblack" # PmenuSel bg = blend(fg_gutter, 0.8, bg)
14
+ p.color :search, hex: "#3d59a1", ansi: "blue" # bg_search = blue0
15
+ p.color :fg, hex: "#c0caf5", ansi: "white" # fg
16
+ p.color :fg_dark, hex: "#a9b1d6", ansi: "white" # fg_dark → statusline fg
17
+ p.color :comment, hex: "#565f89", ansi: "brightblack" # comment
18
+
19
+ # Accent colors
20
+ p.color :blue, hex: "#7aa2f7", ansi: "blue" # Function, Directory, link
21
+ p.color :cyan, hex: "#7dcfff", ansi: "cyan" # PreProc, Keyword (base groups)
22
+ p.color :purple, hex: "#9d7cd8", ansi: "magenta" # @keyword (treesitter default)
23
+ p.color :magenta, hex: "#bb9af7", ansi: "magenta" # Identifier, Statement
24
+ p.color :green, hex: "#9ece6a", ansi: "green" # String
25
+ p.color :teal, hex: "#73daca", ansi: "cyan" # @property, @variable.member
26
+ p.color :orange, hex: "#ff9e64", ansi: "yellow" # Constant
27
+ p.color :red, hex: "#f7768e", ansi: "red" # @variable.builtin, flagged files
28
+ p.color :blue1, hex: "#2ac3de", ansi: "cyan" # Type, Special
29
+ p.color :blue5, hex: "#89ddff", ansi: "cyan" # Operator, punctuation delimiters
30
+ end
31
+
32
+ t.default_colors foreground: :fg, background: :bg
33
+
34
+ # Programming faces
35
+ t.face :comment, foreground: :comment
36
+ t.face :preprocessing_directive, foreground: :cyan # PreProc = c.cyan
37
+ t.face :keyword, foreground: :purple # @keyword = c.purple (treesitter)
38
+ t.face :string, foreground: :green # String = c.green
39
+ t.face :number, foreground: :orange # Number → Constant = c.orange
40
+ t.face :constant, foreground: :orange # Constant = c.orange
41
+ t.face :function_name, foreground: :blue # Function = c.blue
42
+ t.face :type, foreground: :blue1 # Type = c.blue1
43
+ t.face :variable, foreground: :magenta # Identifier = c.magenta
44
+ t.face :operator, foreground: :blue5 # Operator = c.blue5
45
+ t.face :punctuation, foreground: :blue5 # @punctuation.delimiter = c.blue5
46
+ t.face :builtin, foreground: :blue1 # Special = c.blue1
47
+ t.face :property, foreground: :teal # @property = c.green1 (teal)
48
+
49
+ # Basic faces
50
+ # StatusLine: fg = fg_dark, bg = bg_dark
51
+ t.face :mode_line, foreground: :fg_dark, background: :bg_dark
52
+ t.face :link, foreground: :blue, underline: true
53
+ t.face :control
54
+ t.face :region, background: :bg_vis # Visual = bg_visual
55
+ # Search: bg = bg_search (blue0 = #3d59a1), fg = fg
56
+ t.face :isearch, foreground: :fg, background: :search
57
+ t.face :floating_window, foreground: :fg, background: :bg_hl
58
+
59
+ # Completion faces
60
+ # Pmenu: bg = bg_dark, fg = fg
61
+ # PmenuSel: bg = blend(fg_gutter, 0.8, bg) ≈ #343a55
62
+ t.face :completion_popup, foreground: :fg, background: :bg_dark
63
+ t.face :completion_popup_selected, foreground: :fg, background: :sel_bg
64
+
65
+ # Dired faces
66
+ t.face :dired_directory, foreground: :blue, bold: true # Directory = c.blue
67
+ t.face :dired_symlink, foreground: :teal
68
+ t.face :dired_executable, foreground: :green
69
+ t.face :dired_flagged, foreground: :red
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Textbringer
2
- VERSION = "24"
2
+ VERSION = "25"
3
3
  end