feat: configure chrome segments and anchor groups

This commit is contained in:
Valdemar Lorenzen
2026-10-12 11:07:40 +02:00
parent d55b7b65d2
commit 4cfd068f1c
14 changed files with 1731 additions and 371 deletions
+85 -13
View File
@@ -1,6 +1,17 @@
# frozen_string_literal: true
module Vamp
# @param name [String, Symbol]
# @return [String]
def self.chrome_name!(name)
name = name.to_s if name.is_a?(Symbol)
name = string!(name, "label/segment name")
unless /\A[A-Za-z_][A-Za-z0-9_]*\z/.match?(name)
raise ArgumentError, "label/segment name must match [A-Za-z_][A-Za-z0-9_]*"
end
name
end
# Collects and validates the Ruby startup configuration DSL.
class Config
# @return [Hash{String => Boolean, Hash{String, Symbol => Object}}] language presets/options
@@ -16,7 +27,9 @@ module Vamp
@file_picker_view = "tree"
@file_explorer_view = "tree"
@clipboard_mode = "system"
@tabline_label = ""
@tabline = {}
@statusline = {}
@labels = {}
@diff_context_lines = 10
@diff_expand_lines = 15
end
@@ -63,10 +76,24 @@ module Vamp
@clipboard_mode = nonempty_string!(mode, "clipboard mode")
end
# @param text [String] plain text displayed at the right of the tab line; empty clears it
# @return [String]
def tabline_label=(text)
@tabline_label = Vamp.string!(text, "tabline label")
# @param options [Hash{String, Symbol => Object}]
# @return [Hash]
def tabline=(options)
@tabline = chrome_line!(options)
end
# @param options [Hash{String, Symbol => Object}]
# @return [Hash]
def statusline=(options)
@statusline = chrome_line!(options)
end
# @param values [Hash{String, Symbol => String}]
# @return [Hash]
def labels=(values)
@labels = chrome_hash!(values).to_h do |name, text|
[Vamp.chrome_name!(name), Vamp.string!(text, "label text")]
end
end
# @param lines [Integer] nonnegative context lines around each diff change
@@ -111,11 +138,51 @@ module Vamp
def response
{ "version" => 1, "type" => "config", "plugins" => @plugins, "lsp" => lsp_options, "bindings" => @bindings,
"leader" => @leader, "file_explorer_side" => @file_explorer_side, "file_picker_view" => @file_picker_view,
"file_explorer_view" => @file_explorer_view, "clipboard_mode" => @clipboard_mode, "tabline_label" => @tabline_label,
"file_explorer_view" => @file_explorer_view, "clipboard_mode" => @clipboard_mode,
"tabline" => @tabline, "statusline" => @statusline, "labels" => @labels,
"diff_context_lines" => @diff_context_lines, "diff_expand_lines" => @diff_expand_lines }
end
private
# @param value [Hash{String, Symbol => Object}]
# @return [Hash{String => Object}]
def chrome_hash!(value)
raise TypeError, "chrome options must be a Hash" unless value.is_a?(Hash)
value.each_with_object({}) do |(key, item), result|
key = key.to_s if key.is_a?(Symbol)
key = Vamp.string!(key, "chrome key")
raise ArgumentError, "duplicate chrome key: #{key}" if result.key?(key)
result[key] = item
end
end
# @param options [Hash{String, Symbol => Object}]
# @return [Hash{String => Object}]
def chrome_line!(options)
chrome_hash!(options).to_h do |name, value|
if %w[left center right].include?(name)
raise TypeError, "#{name} must be an Array" unless value.is_a?(Array)
[name, value.map { |item| Vamp.chrome_name!(item) }]
else
Vamp.chrome_name!(name)
style = chrome_hash!(value).to_h do |option, item|
case option
when "padding"
unless item.is_a?(Integer) && item.between?(0, 64)
raise ArgumentError, "padding must be an Integer between 0 and 64"
end
when "title", "leading_edge", "trailing_edge", "first_leading_edge"
item = Vamp.string!(item, option)
else
raise ArgumentError, "unknown chrome style option: #{option}"
end
[option, item]
end
[name, style]
end
end
end
# @param value [Integer]
# @param label [String]
@@ -244,10 +311,12 @@ module Vamp
queue("message", text)
end
# @param text [String] plain text displayed at the right of the tab line; empty clears it
# @param name [String, Symbol]
# @param text [String] named session-wide plain text; empty clears it
# @return [nil]
def tabline_label(text)
queue("tabline_label", text)
def label(name, text)
name = Vamp.chrome_name!(name)
queue("label", text, name)
end
private
@@ -294,15 +363,18 @@ module Vamp
raise ArgumentError, "context buffer_id and revision must be nonnegative integers"
end
# @param type [String] insert, replace, message, or tabline_label
# @param type [String] insert, replace, message, or label
# @param text [String]
# @param name [String, nil]
# @return [nil]
def queue(type, text)
def queue(type, text, name = nil)
text = Vamp.string!(text, "effect text")
@effect_bytes += text.bytesize
@effect_bytes += text.bytesize + (name ? name.bytesize : 0)
raise ArgumentError, "effects exceed 4 MiB" if @effect_bytes > MAX_FRAME
@effects << { "type" => type, "text" => text }
effect = { "type" => type, "text" => text }
effect["name"] = name if name
@effects << effect
nil
end
end