typr 1.7.0 → 1.8.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 +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +1 -1
- data/lib/browser.rb +2 -3
- data/lib/grid.rb +2 -2
- data/lib/line.rb +2 -2
- data/lib/terminal.rb +17 -11
- data/lib/text.rb +8 -10
- data/typr.gemspec +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 02fb4a45192b9a6bc2b3a751033a71e058b2abcb33b77d8873c991a2d6031dd1
|
|
4
|
+
data.tar.gz: 878f286e0c40eb45b0b5c5216633bc0a9ff82c7f6bc03d18531a80090936e2af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 921906f7edae965d3ea48ed62e8eae91a770ad63dcf7cc3f20bb8463c9bbef280bcca2d2577317e4dd6c71d48b3740630bfaedf2d8c617cc9878d01381eebb9e
|
|
7
|
+
data.tar.gz: d0db793255d8969a1181193dee6b06227efc2c0248fff99ca6407f6d5944ece37dc330e8cdabafa26229e98a299a576ebc245ea4e4ebd5a25661b20526d094cc
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [vx.y.z] — __DATE__
|
|
4
4
|
|
|
5
|
+
## [v1.8.0] — 2026-10-11
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- Sort indicator uses solid triangles (▲▼) instead of thin arrows, for a heavier mark at the same single-cell width
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Text paints new spans once at entry and rebuilds only reflow: scheme and content colors survive resizes and appends without stacking or stripping
|
|
12
|
+
- Terminal self-test renders without scrolling and covers all named colors — status line uses raw output on the last row (`p` scrolled with inspect quotes and a newline), rows are capped to the visible area, the 256-ramp starts at a known position, the color list includes all `COLOR_MAP` names plus the full grey ramp, and the fg/bg steppers clamp to valid ids
|
|
13
|
+
- String headers fit inside minimal-width boxes — the box ignored the margin in the header width, so the border overwrote the last header character; single `:max` columns provably span the widget width
|
|
14
|
+
- Word jumps are documented as alt-arrow, not ctrl-arrow — README, the `read_line` doc comment, and the v1.2.0 entry called them ctrl-arrow while the bindings are `KEY_ALT_LEFT`/`KEY_ALT_RIGHT` (SGR modifier 3 = alt); the package's key modifier is alt everywhere
|
|
15
|
+
- Command-line redraw overwrites in place — `read_line` cleared the row on every keypress, flashing on cursor moves; each frame now pads to end-of-line with spaces instead, so shrinking content leaves no ghosts either
|
|
16
|
+
- Cursor stays hidden while the command line redraws — every keypress parked the visible cursor at the prompt between the home move and the edit-position move; each frame now hides it first and shows it at the edit position
|
|
17
|
+
- Mode table corrected to standard SGR order (`dim` restored, so `slow→5` and `invert→7`) with `:steady` at position 25 for blink-off; `mode_code` stays index-by-position
|
|
18
|
+
|
|
5
19
|
## [v1.7.0] — 2026-10-02
|
|
6
20
|
|
|
7
21
|
### Fixed
|
|
@@ -100,7 +114,7 @@
|
|
|
100
114
|
## [v1.2.0] — 2026-08-02
|
|
101
115
|
|
|
102
116
|
### Added
|
|
103
|
-
- `Typr.read_key` / `Typr.read_line` — the public terminal input API: `read_key` reads a raw key; `read_line` is the shared interactive line editor that renders a prompt + query at any position with arrow keys,
|
|
117
|
+
- `Typr.read_key` / `Typr.read_line` — the public terminal input API: `read_key` reads a raw key; `read_line` is the shared interactive line editor that renders a prompt + query at any position with arrow keys, alt-arrow word jumps, Home/End/Delete/Backspace, Escape aborts (`nil`), Enter confirms, and an optional block runs after each keypress
|
|
104
118
|
- `Line#ask` strict question types — `Array` (pick from an object/column), `:key`, `:line`; the question and answer are rendered in `@colors[:question]`/`@colors[:answer]`
|
|
105
119
|
- `Line#align` attribute (`:left`/`:right`) for text alignment in draw
|
|
106
120
|
- `dark_*` named colors (`dark_red`, `dark_green`, `dark_yellow`, `dark_blue`, `dark_magenta`, `dark_cyan`) and a `COLOR_MAP` of popular named colors in `color_code`
|
data/README.md
CHANGED
|
@@ -185,7 +185,7 @@ Clears the full screen or a single line (`:line`).
|
|
|
185
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.
|
|
186
186
|
|
|
187
187
|
### `Typr.read_line(prompt, ...)`
|
|
188
|
-
The shared interactive line editor. Renders a prompt and query at any position with arrow keys,
|
|
188
|
+
The shared interactive line editor. Renders a prompt and query at any position with arrow keys, alt-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.
|
|
189
189
|
|
|
190
190
|
```ruby
|
|
191
191
|
Typr.read_line "/", completions: ->(query, cursor) {
|
data/lib/browser.rb
CHANGED
|
@@ -503,7 +503,7 @@ full: %i[ name size permissions executable printable owner group
|
|
|
503
503
|
input: [ [->{Etc.getpwuid(Process.euid).name rescue ENV["USER"] || Etc.getlogin}, ->{@parent.directory},
|
|
504
504
|
->{@parent.filter_display},
|
|
505
505
|
->{ (s = @parent.sorted_by(true)) &&
|
|
506
|
-
"#{s} #{@parent.reverse ? "\
|
|
506
|
+
"#{s} #{@parent.reverse ? "\u25BC" : "\u25B2"}"},
|
|
507
507
|
->{@parent.view} ] ], format: [:min, :max, :min, :min, :min],
|
|
508
508
|
colors: { columns: [@colors[:default], @colors[:default],
|
|
509
509
|
@colors[:actions][:filter], @colors[:actions][:sort],
|
|
@@ -549,7 +549,7 @@ full: %i[ name size permissions executable printable owner group
|
|
|
549
549
|
wire.(label, cmd)
|
|
550
550
|
end
|
|
551
551
|
@user ||= Line.new( parent:self, left:->{@parent.left}, top:->{@parent.bottom+1},
|
|
552
|
-
|
|
552
|
+
bindings: bindings_labels )
|
|
553
553
|
else
|
|
554
554
|
cmds = { "[h]elp" => :help, "[/]:search" => :search,
|
|
555
555
|
"[f]ilter" => :filter_view, "[s]ort" => :sort_view, "[v]iews" => :views,
|
|
@@ -563,7 +563,6 @@ full: %i[ name size permissions executable printable owner group
|
|
|
563
563
|
[i]nvert_mark [~]:home [H]idden_files [back]:.. [up] [down] [pageup] [pagedown] [home] [end] [esc]:quit [return]:confirm\ ]
|
|
564
564
|
plain.each { |label| wire.(label, cmds[label]) if cmds[label] }
|
|
565
565
|
@user ||= Line.new( parent:self, left:->{@parent.left}, top:->{@parent.bottom+1},
|
|
566
|
-
colors: { regex: @colors[:regex] },
|
|
567
566
|
bindings: plain.map { |label|
|
|
568
567
|
name = label.gsub( /[\[\]]/, '' ).downcase.to_sym
|
|
569
568
|
@colors[:actions][name] ?
|
data/lib/grid.rb
CHANGED
|
@@ -411,7 +411,7 @@ module Typr
|
|
|
411
411
|
gaps = @margin.size + @separator.size * (columns - 1)
|
|
412
412
|
sum = @widths.sum
|
|
413
413
|
@max = sum + gaps - 1
|
|
414
|
-
@max = [ @max, @header.length ].max if @header.is_a?(String)
|
|
414
|
+
@max = [ @max, @header.length + @margin.size ].max if @header.is_a?(String)
|
|
415
415
|
space = width - gaps
|
|
416
416
|
if (extra = sum - space ) > 0
|
|
417
417
|
extra.times{ |i| @widths[ @widths.index(@widths.max) ] -= 1 }
|
|
@@ -434,7 +434,7 @@ module Typr
|
|
|
434
434
|
def print row=nil
|
|
435
435
|
return super unless row
|
|
436
436
|
header = ( row == :header )
|
|
437
|
-
return draw @header[0
|
|
437
|
+
return draw @header[0...(width - @margin.size)].ljust(width - @margin.size) if
|
|
438
438
|
header and @header.is_a? String
|
|
439
439
|
return unless row_data = header ? @header : @data[row]
|
|
440
440
|
fields = row_data.dup
|
data/lib/line.rb
CHANGED
|
@@ -159,13 +159,13 @@ class Line < Space
|
|
|
159
159
|
# line.cli "> ", initial: "cp %name"
|
|
160
160
|
# #=> "cp source.txt" (or nil on Escape)
|
|
161
161
|
|
|
162
|
-
def cli prompt, initial: '', redraw: nil, history: nil, prefixes: nil
|
|
162
|
+
def cli prompt, initial: '', redraw: nil, history: nil, prefixes: nil, regex: nil
|
|
163
163
|
re = /\A[#{Regexp.escape(prefixes || '|+=!')}]/
|
|
164
164
|
source = ->(query) {
|
|
165
165
|
bash_candidates(query.sub(re, '')).split("\n").reject(&:empty?).uniq }
|
|
166
166
|
colored = color_code(@colors[:default]).to_s + prompt + color_code(@colors[:answer])
|
|
167
167
|
Typr.read_line(colored, left: left, top: top, initial: initial,
|
|
168
|
-
completions: source, redraw: redraw, regex: @colors[:regex], history: history)
|
|
168
|
+
completions: source, redraw: redraw, regex: regex || @colors[:regex], history: history)
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
private
|
data/lib/terminal.rb
CHANGED
|
@@ -86,7 +86,8 @@ module Typr
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# Text attributes (reset, bold, italic, ...) and named 8/256-color tables.
|
|
89
|
-
MODES = %i[ reset bold italic underline slow fast invert ]
|
|
89
|
+
MODES = %i[ reset bold dim italic underline slow fast invert ]
|
|
90
|
+
MODES[25] = :steady
|
|
90
91
|
COLORS = %i[ black red green yellow blue magenta cyan white ]
|
|
91
92
|
COLOR_MAP = {
|
|
92
93
|
brown: 130, orange: 208, lime: 118, pink: 218,
|
|
@@ -407,7 +408,7 @@ module Typr
|
|
|
407
408
|
## Interactive line editor used for string prompts (search, %str, ...).
|
|
408
409
|
#
|
|
409
410
|
# Renders +prompt+ and the query at (left, top) and edits it with
|
|
410
|
-
# arrow keys,
|
|
411
|
+
# arrow keys, alt-arrow word jumps, home/end, delete and backspace.
|
|
411
412
|
# Returns the query on enter, nil on escape. A block may inspect each
|
|
412
413
|
# keypress after it is applied; a non-nil return short-circuits the
|
|
413
414
|
# editor and becomes its return value. When stdin is not a tty, the
|
|
@@ -434,13 +435,16 @@ module Typr
|
|
|
434
435
|
$>.print CURSOR_NORMAL
|
|
435
436
|
begin
|
|
436
437
|
loop do
|
|
438
|
+
$>.print CURSOR_INVISIBLE
|
|
437
439
|
$>.print "\e[%i;%if" % [ top + 1, left + 1 ]
|
|
438
|
-
$>.print ERASE_LINE
|
|
439
440
|
before = text_width( prompt + query[0...cursor] )
|
|
440
441
|
offset = [ left + before - Typr.width, 0 ].max
|
|
441
442
|
display = prompt + paint( query, regex, prompt[/\e\[[0-9;]*m\z/].to_s )
|
|
442
|
-
|
|
443
|
+
line = slice_width( display, offset, Typr.width - left + 1 )
|
|
444
|
+
$>.print line
|
|
445
|
+
$>.print ' ' * (Typr.width - left + 1 - text_width(line))
|
|
443
446
|
$>.print "\e[%i;%if" % [ top + 1, left + 1 + before - offset ]
|
|
447
|
+
$>.print CURSOR_NORMAL
|
|
444
448
|
key = read_key
|
|
445
449
|
return nil if key.nil? or key == KEY_ESCAPE
|
|
446
450
|
return query if key == KEY_RETURN or key == "\n"
|
|
@@ -619,14 +623,15 @@ if __FILE__ == $0
|
|
|
619
623
|
begin
|
|
620
624
|
include Typr
|
|
621
625
|
Typr.init
|
|
622
|
-
colors = COLORS + (
|
|
626
|
+
colors = COLORS + COLOR_MAP.keys.map(&:to_s) + (0..10).map{|i| "grey#{i*10}" }
|
|
623
627
|
chars = (33..126).map(&:chr)
|
|
624
628
|
slice = chars.count / colors.count + 1
|
|
625
629
|
characters = chars.each_slice( slice ).map(&:join)
|
|
626
630
|
key,fg,bg = "",150,0
|
|
627
631
|
Typr.clear
|
|
632
|
+
rows = [colors.count, Typr.height - 4].min
|
|
628
633
|
loop do
|
|
629
|
-
colors.each_with_index{ |color,y|
|
|
634
|
+
colors.first(rows).each_with_index{ |color,y|
|
|
630
635
|
characters.each_with_index{ |chars,x|
|
|
631
636
|
foreground color.to_sym;
|
|
632
637
|
background colors[x].to_sym;
|
|
@@ -634,20 +639,21 @@ begin
|
|
|
634
639
|
draw chars
|
|
635
640
|
}
|
|
636
641
|
}
|
|
642
|
+
move 0, rows
|
|
637
643
|
(0...256).each{ |i| background i; draw ' ' }
|
|
638
644
|
|
|
639
645
|
move 0, Typr.height
|
|
640
646
|
color [:white, :black]
|
|
641
|
-
|
|
647
|
+
draw "KEY: %s / %s" % [key, key]
|
|
642
648
|
move 15, Typr.height
|
|
643
649
|
color [fg,bg]
|
|
644
650
|
print " %s / %s " % [fg,bg]
|
|
645
651
|
key = Typr.read_key
|
|
646
652
|
case key
|
|
647
|
-
when KEY_UP; fg
|
|
648
|
-
when KEY_DOWN; fg
|
|
649
|
-
when KEY_LEFT; bg
|
|
650
|
-
when KEY_RIGHT; bg
|
|
653
|
+
when KEY_UP; fg = [fg + 1, 255].min
|
|
654
|
+
when KEY_DOWN; fg = [fg - 1, 0].max
|
|
655
|
+
when KEY_LEFT; bg = [bg - 1, 0].max
|
|
656
|
+
when KEY_RIGHT; bg = [bg + 1, 255].max
|
|
651
657
|
when KEY_ESCAPE; exit
|
|
652
658
|
end
|
|
653
659
|
end
|
data/lib/text.rb
CHANGED
|
@@ -33,13 +33,19 @@ module Typr
|
|
|
33
33
|
# text << "appended line" # alias for build
|
|
34
34
|
|
|
35
35
|
def build input=nil
|
|
36
|
-
( input, @data, @lines =
|
|
36
|
+
( input, @data, @lines = @data, "", [0] ) if rebuild = !input
|
|
37
37
|
return self if rebuild && input == ""
|
|
38
|
-
rows = @lines[0...-1].each_index.map{ |i|
|
|
38
|
+
rows = @lines[0...-1].each_index.map{ |i| @data[@lines[i]...@lines[i+1]] }
|
|
39
39
|
@data = rows.join
|
|
40
40
|
off = [ 0 ]; rows.each{ |row| off << off.last + row.length }
|
|
41
41
|
@lines = off
|
|
42
42
|
str = input.respond_to?(:read) ? input.read : input.to_s
|
|
43
|
+
if !rebuild and (r = @colors[:regex]) and r != {}
|
|
44
|
+
base = color_code( @colors[:default][0] ).to_s
|
|
45
|
+
# Paint new spans once, whole (multiline matches included); rebuilds
|
|
46
|
+
# below only reflow, so paint can neither stack nor need stripping.
|
|
47
|
+
str = Typr.paint(str, r, base)
|
|
48
|
+
end
|
|
43
49
|
str = str.gsub("\t", " " * @tabspace)
|
|
44
50
|
@tail = ""
|
|
45
51
|
pos = 0
|
|
@@ -85,14 +91,6 @@ module Typr
|
|
|
85
91
|
end
|
|
86
92
|
end
|
|
87
93
|
@lines << @data.length unless @lines.last == @data.length
|
|
88
|
-
if (r = @colors[:regex]) and r != {}
|
|
89
|
-
base = color_code( @colors[:default][0] ).to_s
|
|
90
|
-
painted = @lines[0...-1].each_index.map{ |i|
|
|
91
|
-
Typr.paint @data[@lines[i]...@lines[i+1]], r, base }
|
|
92
|
-
@data = painted.join
|
|
93
|
-
off = [ 0 ]; painted.each{ |line| off << off.last + line.length }
|
|
94
|
-
@lines = off
|
|
95
|
-
end
|
|
96
94
|
highlight if @re
|
|
97
95
|
end
|
|
98
96
|
alias :<< :build
|
data/typr.gemspec
CHANGED
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.
|
|
4
|
+
version: 1.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kilian Reitmayr
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-11 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: unicode-display_width
|