typr 1.6.0 → 1.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fc328e46b4b4d36e0d3f68eb0a50f8068934469ec5e9d5d84099755685732ad
4
- data.tar.gz: 254c5a5842474b4fc550a0aff5fbaa772e961a6aca9a9a8f90ed1a89cc761e51
3
+ metadata.gz: 75b5f8bf6bcd9c1e957f87f8ef47eaec83784cefcc3903ea9e68b25f0280d7af
4
+ data.tar.gz: 1e92d998f96105408ac13e6c43f49ae2a44cdf0b2e6e34596f55749228beff29
5
5
  SHA512:
6
- metadata.gz: eeae3cd67ce492706bc952e8422adea09d300f115928c074411c2589f5dae577ff4ad73e610e6a9b279007a93205e81fa9579c59d3f404f2778f52b06cb26e24
7
- data.tar.gz: 735a2236dbd0868674f4727572f578237f34165ab04d683179dd45464918099719c422503b386915f2df4895f1d5228550e6ee9bc25a9bf607d650eff8e8153c
6
+ metadata.gz: 3fb8fb7f24580c81250951138b3600037ce3eef21acc48a17c79db4c3fe5cceddd8037e1cb04548d85d2fde048426fa90c08846b09b9c8b2ad06472106813058
7
+ data.tar.gz: 83f72c57b64e9515c27ddea087bdce0ad2d935e98b697a7e8b5d0de9885aa9dab18f15143437e4b8f0136899d5a6b08c5b7712dbd8f5b8d2f41ab56cb8c5d598
data/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## [vx.y.z] — __DATE__
4
4
 
5
+ ## [v1.7.0] — 2026-10-02
6
+
7
+ ### Fixed
8
+ - Column hints in `pick :column` sit in the gap cell left of each column — `draw_hints` positioned them from the widget edge while rows render past the margin, so every hint landed one margin-width left of its column; overlaying the column starts overshot right instead
9
+ - Default bottom-bar commands work in a bare browser — the key labels were display-only, so `h / f s v r m M a i ~ H` did nothing; the default bindings now populate the keymap like explicit ones, and the pick loop discards command results instead of misreading them as picks
10
+ - `[d]irectories` left the default bar — directory history is a filecon feature; typr's unrelated `Browser#directories` row query is unchanged
11
+ - Explicit nil widget boundaries fall back to safe defaults — the unified clamp referenced the accessor itself, recursing until `SystemStackError` (and the bottom default assumed subclass-only methods); per-name fallbacks are restored inside the clamp
12
+
13
+ ### Changed
14
+ - Regex color schemes are named and opt-in — `regex:` accepts a Hash as before or a Symbol that `Typr.paint` resolves through `REGEX_SCHEMES` (`:generic` paints numbers, colon keys, quotes, brackets, and punctuation; `:shell` paints a command line's first word and `--options`); unknown symbols raise `ArgumentError`. `Text` and `Line` no longer install a default scheme, so `regex:` is empty by default and help pages, error popups, and unconfigured views render unpainted
15
+
16
+ ## [v1.6.1] — 2026-10-02
17
+
18
+ ### Fixed
19
+ - `Typr.paint` leaves pre-existing ANSI escapes byte-identical — the regex union matched escape bytes (`ESC`, `[`, `;`, digits) as ordinary text, shredding sequences already in the string; downstream clipping then dropped the orphaned `ESC` bytes and the bare sequence bodies printed as literal text (filecon help titles showed `[38;2;…m`). Paint now matches text runs between escapes only
20
+
5
21
  ## [v1.6.0] — 2026-09-30
6
22
 
7
23
  ### Added
data/README.md CHANGED
@@ -31,9 +31,9 @@ The default terminal frontend is pure ANSI on raw TTY input — **no ncurses**.
31
31
 
32
32
  ### Colors
33
33
 
34
- Named colors (basic, shades, and `dark_*`), grey shades `grey0`–`grey100`, the terminal's 8-bit palette, and RGB triplets for true-color terminals. Every component takes a per-part `colors:` hash (columns, headers, hints, search matches, …). A component-level `regex:` key maps `Regexp => color` to tint typed input (`Typr.read_line`/`Line#cli`) and the rows of `Typr::Text` areas; when two patterns match the same span the earlier key wins, so order overlapping patterns longest-first. Colors may be any value `color_code` accepts — named color, `greyN`, an 8-bit index, an RGB triplet like `[10, 200, 30]`, or a `[fg, bg]` pair. Header bars render bold by default.
34
+ Named colors (basic, shades, and `dark_*`), grey shades `grey0`–`grey100`, the terminal's 8-bit palette, and RGB triplets for true-color terminals. Every component takes a per-part `colors:` hash (columns, headers, hints, search matches, …). A component-level `regex:` key maps `Regexp => color` to tint typed input (`Typr.read_line`/`Line#cli`) and the rows of `Typr::Text` areas, or names a scheme — `:generic` or `:shell`; when two patterns match the same span the earlier key wins, so order overlapping patterns longest-first. Colors may be any value `color_code` accepts — named color, `greyN`, an 8-bit index, an RGB triplet like `[10, 200, 30]`, or a `[fg, bg]` pair. Header bars render bold by default.
35
35
 
36
- `Typr::Text` paints numbers cyan, colon-separated keys yellow, quoted strings green, bracketed groups magenta, and remaining punctuation grey — override with `regex:`, disable with `regex: {}`. Each painted span restores only the `default` foreground, so the row's own background (alternating stripes, search highlight, padding) survives; `Line#cli` colors the typed command (first word red, `--options` blue); it no longer tints the completion grid. Set `regex: {}` to turn a scheme off.
36
+ Pass `regex: :generic` and `Typr::Text` paints numbers cyan, colon-separated keys yellow, quoted strings green, bracketed groups magenta, and remaining punctuation grey — override with a custom map, disable with `regex: {}` (the default: unpainted). Each painted span restores only the `default` foreground, so the row's own background (alternating stripes, search highlight, padding) survives; `Line#cli` colors the typed command with the `:shell` scheme (first word red, `--options` blue) when configured; it no longer tints the completion grid. Set `regex: {}` to turn a scheme off.
37
37
 
38
38
  ### Frontends
39
39
 
@@ -114,8 +114,7 @@ Typr.init
114
114
 
115
115
  @browser = Typr::Browser.new(
116
116
  directory: "/tmp",
117
- right: -1, bottom: -1,
118
- colors: { hints: [:white, :black] }
117
+ right: -1, bottom: -1
119
118
  )
120
119
 
121
120
  selected = @browser.pick # interactive file picker, returns the absolute path
@@ -186,7 +185,7 @@ Clears the full screen or a single line (`:line`).
186
185
  Reads a single keypress in raw mode. Returns the key as a String (`KEY_ESCAPE`, `?q`, arrow escape sequences), a `Typr::Mouse` struct for mouse reports, or `nil` when input is unavailable.
187
186
 
188
187
  ### `Typr.read_line(prompt, ...)`
189
- The shared interactive line editor. Renders a prompt and query at any position with arrow keys, ctrl-arrow word jumps, Home/End/Delete/Backspace; Enter confirms, Escape aborts (`nil`). An optional block runs after each keypress and may short-circuit with a result. Pass `completions:` — a callable `->(query, cursor) { candidates }` — and TAB matches the current word against `candidates` in a pick grid: a candidate is either a string or `[text, color-pair]` to tint its pick entry. Pass `regex:` — a Hash of `Regexp => color` — and matching regions of the query are colored as they are typed, restoring the prompt's trailing color code. The editor is agnostic to where candidates come from.
188
+ The shared interactive line editor. Renders a prompt and query at any position with arrow keys, ctrl-arrow word jumps, Home/End/Delete/Backspace; Enter confirms, Escape aborts (`nil`). An optional block runs after each keypress and may short-circuit with a result. Pass `completions:` — a callable `->(query, cursor) { candidates }` — and TAB matches the current word against `candidates` in a pick grid: a candidate is either a string or `[text, color-pair]` to tint its pick entry. Pass `regex:` — a Hash of `Regexp => color`, or a scheme name (`:generic`, `:shell`) — and matching regions of the query are colored as they are typed, restoring the prompt's trailing color code. The editor is agnostic to where candidates come from.
190
189
 
191
190
  ```ruby
192
191
  Typr.read_line "/", completions: ->(query, cursor) {
@@ -203,7 +202,7 @@ Strict question types:
203
202
  The question and answer are rendered in `@colors[:question]`/`@colors[:answer]`.
204
203
 
205
204
  ### `Line#cli`
206
- Prompts for a single command line with TAB completion matched against the shell (bash commands, options, and files). `completions: true` switches on the content; `initial:` seeds the line; `redraw:` repaints while the completion grid is up. The typed command tints with `@colors[:regex]` — default red for the first word, blue for `--options`. Completion candidates are plain strings.
205
+ Prompts for a single command line with TAB completion matched against the shell (bash commands, options, and files). `completions: true` switches on the content; `initial:` seeds the line; `redraw:` repaints while the completion grid is up. With `regex: :shell` the typed command tints red for the first word, blue for `--options`. Completion candidates are plain strings.
207
206
 
208
207
  ```ruby
209
208
  line.cli "> ", initial: "cp %name %dir", completions: true, redraw: -> { show }
data/example/browser CHANGED
@@ -4,35 +4,40 @@
4
4
  # Usage:
5
5
  # cd example && ruby browser
6
6
  # ruby browser /path/to/dir Start in a specific directory
7
- # ruby browser --select Start in pick mode (returns path)
8
7
  #
9
8
  # Navigates directories and displays files with size and type.
10
9
  # Pass a directory path as an argument to start there.
11
- # Pass --select to enter pick mode — selected file is printed to stdout on exit.
10
+ # The picked file path is printed to stdout on exit.
12
11
  #
13
12
  # Keys:
14
- # arrows / jk Navigate up/down
15
- # enter Open directory or pick file (in select mode)
16
- # / Filter files by name
17
- # esc Exit
13
+ # arrows Scroll up/down
14
+ # pgup/pgdn Page up/down
15
+ # home/end Jump to top/bottom
16
+ # tab Cycle hint characters
17
+ # 1-9,0 Jump to the hinted row (directories change into, files pick)
18
+ # enter Open directory or pick file (returns current directory)
19
+ # h Keybinding help
20
+ # / Live-search names
21
+ # f/s/v Filter/sort/views popups
22
+ # r/m/M/a/i Reset, mark, mark range, mark all, invert marks
23
+ # ~/H Home directory, toggle hidden files
24
+ # esc Exit
18
25
  #
19
- # When run with --select, the chosen file path is printed
20
- # to stdout after the TUI exits (piped to calling process).
26
+ # Click a row to open it; click a bottom-bar label to run that command.
21
27
 
22
28
  require_relative '../lib/typr.rb'
23
29
 
24
30
  class BrowserTest
25
31
  include Typr
26
32
  def initialize
27
- Typr.init
28
- $conf=$*.map{|arg| [arg.start_with?(/\w/), arg] }.to_h
29
- @browser = Browser.new( right: -1, bottom: -1,
30
- directory: $conf[false], colors: { hints: [:white, :black] } )
33
+ Typr.init
34
+ dirs = ARGV.reject{|arg| arg.start_with?('--') }
35
+ @browser = Browser.new( right: -1, bottom: -1, directory: dirs.first )
31
36
  end
32
37
 
33
38
  def run
34
39
  Typr.clear
35
- $file = @browser.pick $conf[true]
40
+ $file = @browser.pick(:file)
36
41
  end
37
42
  end
38
43
 
@@ -40,6 +45,5 @@ begin
40
45
  BrowserTest.new.run
41
46
  ensure
42
47
  Typr.exit
43
- puts $file
44
- end
45
-
48
+ puts $file if $file
49
+ end
data/example/grid CHANGED
@@ -38,10 +38,11 @@ class GridTest
38
38
  @user = Line.new( top: -1, default:
39
39
  "(s)ort, (f)ilter, (r)eset, select (R)ows/(C)olumns/(F)ields, [esc] quit")
40
40
  @head = Line.new( interval: 1,
41
- default: proc{ draw " %s, sort:%s filter:%s selected:%s" %
41
+ default: proc{ draw " %s, sort:%s filter:%s" %
42
42
  [ Time.now.strftime("%D %T"),
43
43
  (@grid.header[@grid.sorted_by] if @grid.sorted_by),
44
- @grid.filters.join, @grid.selected ] } )
44
+ @grid.filters.join ] } )
45
+ @head.reset
45
46
  end
46
47
 
47
48
  def run
data/example/text CHANGED
@@ -26,9 +26,7 @@
26
26
  require_relative '../lib/typr.rb'
27
27
 
28
28
  class TextTest
29
- # extend Typr
30
29
  include Typr
31
- # Typr.frontend :terminal
32
30
  def initialize
33
31
  Typr.init
34
32
  @text = Text.new(
@@ -47,7 +45,7 @@ class TextTest
47
45
  loop do
48
46
  @text.show
49
47
  @user.show
50
- case key = Typr.read( :key )
48
+ case key = Typr.read_key
51
49
  when KEY_ESCAPE; exit
52
50
  when ?/; @text.search
53
51
  when ?w; @user.ask( 'pick word': [@text, :field] )
data/lib/browser.rb CHANGED
@@ -340,6 +340,7 @@ module Typr
340
340
  choice = send key
341
341
  next if choice == :scroll or choice == :outside
342
342
  else
343
+ if @command_keys.include? key then send key; next end
343
344
  next unless choice = send( key )
344
345
  end
345
346
  next unless choice
@@ -529,6 +530,15 @@ full: %i[ name size permissions executable printable owner group
529
530
  ( pre + ( pre.end_with?( "/" ) ? "" : text[pre.length..-1][/\A[^\/]*/] ) ).sub( %r{(?<=.)/$}, "" )
530
531
  end
531
532
 
533
+ @command_keys = []
534
+ wire = ->(label, cmd) {
535
+ key = extract_key(label)
536
+ next unless key
537
+ method = cmd.is_a?(Symbol) ? cmd :
538
+ (cmd.start_with?('!') ? cmd[1..-1].to_sym : cmd.to_sym)
539
+ @keymap[method] = key
540
+ @command_keys << key if key.size == 1
541
+ }
532
542
  if args[:bindings]
533
543
  bindings_labels = []
534
544
  args[:bindings].each do |label, cmd|
@@ -536,20 +546,28 @@ full: %i[ name size permissions executable printable owner group
536
546
  colored = @colors[:actions][name] ?
537
547
  color_code( @colors[:actions][name] ) + label + color_code(@colors[:default]) : label
538
548
  bindings_labels << colored
539
- key = extract_key(label)
540
- next unless key
541
- method = cmd.start_with?('!') ? cmd[1..-1].to_sym : cmd.to_sym
542
- @keymap[method] = key
549
+ wire.(label, cmd)
543
550
  end
544
551
  @user ||= Line.new( parent:self, left:->{@parent.left}, top:->{@parent.bottom+1},
545
- bindings: bindings_labels )
552
+ colors: { regex: @colors[:regex] }, bindings: bindings_labels )
546
553
  else
547
- @user ||= Line.new( parent:self, left:->{@parent.left},top:->{@parent.bottom+1},
548
- bindings: %w[ [h]elp [/]:search ] + @colors[:actions].map{|name,color|
549
- label = "[" + name.to_s[0] + "]" + name.to_s[1..]
550
- color_code( color ) + label + color_code(@colors[:default]) } +
551
- %w[ [r]eset [d]irectories [m]ark [M]ark_range mark_[a]ll
552
- [i]nvert_mark [~]:home [H]idden_files [back]:.. [up] [down] [pageup] [pagedown] [home] [end] [esc]:quit [return]:confirm\ ])
554
+ cmds = { "[h]elp" => :help, "[/]:search" => :search,
555
+ "[f]ilter" => :filter_view, "[s]ort" => :sort_view, "[v]iews" => :views,
556
+ "[r]eset" => :reset_view, "[m]ark" => :mark,
557
+ "[M]ark_range" => :mark_range, "mark_[a]ll" => :mark_all,
558
+ "[i]nvert_mark" => :mark_invert, "[~]:home" => :home,
559
+ "[H]idden_files" => :toggle_hidden }
560
+ plain = ["[h]elp", "[/]:search"] +
561
+ @colors[:actions].map { |name, _| "[" + name.to_s[0] + "]" + name.to_s[1..] } +
562
+ %w[ [r]eset [m]ark [M]ark_range mark_[a]ll
563
+ [i]nvert_mark [~]:home [H]idden_files [back]:.. [up] [down] [pageup] [pagedown] [home] [end] [esc]:quit [return]:confirm\ ]
564
+ plain.each { |label| wire.(label, cmds[label]) if cmds[label] }
565
+ @user ||= Line.new( parent:self, left:->{@parent.left}, top:->{@parent.bottom+1},
566
+ colors: { regex: @colors[:regex] },
567
+ bindings: plain.map { |label|
568
+ name = label.gsub( /[\[\]]/, '' ).downcase.to_sym
569
+ @colors[:actions][name] ?
570
+ color_code( @colors[:actions][name] ) + label + color_code(@colors[:default]) : label } )
553
571
  end
554
572
  cd @directory
555
573
  end
data/lib/line.rb CHANGED
@@ -153,8 +153,8 @@ class Line < Space
153
153
  # line's default color, typed input in the answer color. When +completions+
154
154
  # is truthy, TAB matches the current word against the shell (commands,
155
155
  # options, files) and replaces it through the pick grid. Regions of the
156
- # typed input matching @colors[:regex] are colored as they are typed: the
157
- # first word red (the command), double-dash options blue.
156
+ # typed input matching @colors[:regex] are colored as they are typed
157
+ # (with the :shell scheme: the first word red, double-dash options blue).
158
158
  #
159
159
  # line.cli "> ", initial: "cp %name"
160
160
  # #=> "cp source.txt" (or nil on Escape)
@@ -204,9 +204,7 @@ class Line < Space
204
204
  @prompt = ?>
205
205
  super
206
206
  @bottom = @top
207
- regex = { /(?:^|\s)--[^\s]+/ => :blue, /\A\S+/ => :red }
208
207
  @colors = { question: :green, answer: :yellow }.merge @colors
209
- @colors[:regex] = regex if @colors[:regex].nil?
210
208
  reset
211
209
  end
212
210
  end
data/lib/space.rb CHANGED
@@ -19,8 +19,11 @@ include Typr
19
19
  def %s_setting; @%s; end
20
20
  def %s
21
21
  max=Typr.#{ name[/left|right/] ? 'width' : 'height' }
22
- if !@%s;[max, #{name=='right' ? 'left+@max' :
23
- 'top+rows-1+headspace'}].min
22
+ if !@%s;[max, #{ case name
23
+ when 'left' then '0'
24
+ when 'top' then '0'
25
+ when 'right' then 'left+@max'
26
+ else 'top+[(respond_to?(:rows) ? rows : 0), 1].max-1+(respond_to?(:headspace) ? headspace : 0)' end }].min
24
27
  elsif @%s.is_a? Proc; @%s.call
25
28
  elsif @%s.is_a? Float; (max * @%s).round
26
29
  elsif @%s.negative?; max+@%s+1
data/lib/stack.rb CHANGED
@@ -101,7 +101,7 @@ module Typr
101
101
  color @colors[ :hints ]
102
102
  if type.to_s[ /column/ ]
103
103
  positions( row_id )[ @hints_start..-1 ].each_with_index{ |pos, idx|
104
- move( left + pos, top + row_id )
104
+ move( [left + @margin.size + pos - 1, left].max, top + row_id )
105
105
  draw @hints[idx] }
106
106
  else
107
107
  bottom = top + headspace + [height, rows].min - 1
data/lib/terminal.rb CHANGED
@@ -239,6 +239,24 @@ module Typr
239
239
  module_function :color_code
240
240
  public :color_code
241
241
 
242
+ # Named regex color schemes, accepted anywhere a +regex:+ map is (Text,
243
+ # Line, read_line, paint). +:generic+ paints numbers, colon keys, quoted
244
+ # strings, bracket groups, and punctuation; +:shell+ paints a command
245
+ # line's first word and double-dash options.
246
+ REGEX_SCHEMES = {
247
+ generic: {
248
+ /\[[^\]]*\]|\([^)]*\)|\{[^}]*\}/ => :magenta,
249
+ /".*?"|'.*?'/ => :green,
250
+ /\b\d+(?:\.\d+)?\b/ => :cyan,
251
+ /\b[\w.-]+:/ => :yellow,
252
+ /[^\w\s]/ => :grey60
253
+ },
254
+ shell: {
255
+ /(?:^|\s)--[^\s]+/ => :blue,
256
+ /\A\S+/ => :red
257
+ }
258
+ }
259
+
242
260
  # Returns +str+ with every region matched by the keys of +regex+ wrapped in
243
261
  # the associated color, restoring +base+ after each region. Non-matching
244
262
  # text passes through untouched. +regex+ may be nil or empty (no-op), and
@@ -247,12 +265,26 @@ module Typr
247
265
  # When two patterns match the same span, the earlier key in the Hash wins,
248
266
  # so order overlapping keys longest-first.
249
267
  #
268
+ # Pre-existing ANSI sequences pass through byte-identical: only the plain
269
+ # text between them is matched, so painting never shreds escapes that are
270
+ # already in the string (and a later clip cannot orphan their bodies as
271
+ # literal text).
272
+ #
250
273
  # Typr.paint "fix WARN now", { /WARN/ => :yellow }, "\e[39;49m"
251
274
  def self.paint str, regex, base
275
+ if regex.is_a? Symbol
276
+ regex = REGEX_SCHEMES.fetch(regex) {
277
+ raise ArgumentError, "unknown regex scheme: #{regex.inspect}" }
278
+ end
252
279
  return str if regex.nil? or regex.empty?
253
- str.gsub( Regexp.union( regex.keys ) ) { |m|
254
- color = regex[ regex.keys.find{ |k| k === m } ]
255
- color_code( color ).to_s + m + base }
280
+ union = Regexp.union( regex.keys )
281
+ ansi = /\e(?:\[[0-9;?]*[ -\/]*[@-~]|\][^\a\e]*(?:\a|\e\\)|[()=><0A])|\e/
282
+ str.scan( /#{ansi}|[^\e]+/ ).map { |run|
283
+ run.start_with?( "\e" ) ? run :
284
+ run.gsub( union ) { |m|
285
+ color = regex[ regex.keys.find{ |k| k === m } ]
286
+ color_code( color ).to_s + m + base }
287
+ }.join
256
288
  end
257
289
 
258
290
  # Read the current background/foreground color pair.
data/lib/text.rb CHANGED
@@ -85,7 +85,7 @@ module Typr
85
85
  end
86
86
  end
87
87
  @lines << @data.length unless @lines.last == @data.length
88
- if (r = @colors[:regex]) and !r.empty?
88
+ if (r = @colors[:regex]) and r != {}
89
89
  base = color_code( @colors[:default][0] ).to_s
90
90
  painted = @lines[0...-1].each_index.map{ |i|
91
91
  Typr.paint @data[@lines[i]...@lines[i+1]], r, base }
@@ -211,15 +211,7 @@ module Typr
211
211
  @data, @lines, @tail = "", [0], ""
212
212
  @search = { pattern: nil, dir: :forward, last: nil, matches: [] }
213
213
  super args
214
- regex = {
215
- /\[[^\]]*\]|\([^)]*\)|\{[^}]*\}/ => :magenta,
216
- /".*?"|'.*?'/ => :green,
217
- /\b\d+(?:\.\d+)?\b/ => :cyan,
218
- /\b[\w.-]+:/ => :yellow,
219
- /[^\w\s]/ => :grey60
220
- }
221
- @colors = { header: :yellow, search: :grey20 }.merge( @colors || {} )
222
- @colors[:regex] = regex if @colors[:regex].nil?
214
+ @colors = { header: :yellow, search: :grey20 }.merge( @colors || {} )
223
215
  @keymap = { search: ?/, search_next: ?n, search_prev: ?p }.merge @keymap
224
216
  @lastwidth = width
225
217
  self << @input
data/typr.gemspec CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "typr"
5
- s.version = "1.6.0"
6
- s.date = "2026-09-30"
5
+ s.version = "1.7.0"
6
+ s.date = "2026-10-02"
7
7
  s.homepage = "https://codeberg.org/typr/typr"
8
8
  s.licenses = ["MIT"]
9
9
  s.require_paths = ["lib"]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kilian Reitmayr
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-09-30 00:00:00.000000000 Z
10
+ date: 2026-10-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: unicode-display_width