kv 0.6.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/exe/kv +1 -1
- data/lib/kv/version.rb +1 -1
- data/lib/kv.rb +89 -39
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 510d5e2565cf1d662da48e3c4af89799375377b594469132319f5475ff53b8ce
|
4
|
+
data.tar.gz: '09136cab7d1f49371444949e563d5ec58225881b6ab7f781711314ea176f4401'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3e76a17edc990f59d1a999cb16d75619852503beafd05c9009c3efb697ccd2712203eeec6e6627614e71cce676f516972e17384588ecc9a24bd0f4acb8c2ae5
|
7
|
+
data.tar.gz: ad6c7de4f61931c05a867554ae47998d0f19f72548fbf76cfb3336fdebca7b06f111e828b17ac21011dd95defa5adb588d70c157b9043b3b897ad612fda7f4b3
|
data/.github/FUNDING.yml
ADDED
data/exe/kv
CHANGED
data/lib/kv/version.rb
CHANGED
data/lib/kv.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "kv/version"
|
4
4
|
require "curses"
|
5
5
|
require 'stringio'
|
6
6
|
require 'optparse'
|
@@ -20,7 +20,8 @@ end
|
|
20
20
|
class Screen
|
21
21
|
RenderStatus = Struct.new(
|
22
22
|
:c_cols, :c_lines, :x, :y, :last_lineno,
|
23
|
-
:search, :goto, :
|
23
|
+
:search, :goto, :wrapping,
|
24
|
+
:line_mode, :ts_mode, :separation_mode,
|
24
25
|
)
|
25
26
|
class RenderStatus
|
26
27
|
def to_s
|
@@ -29,9 +30,18 @@ class Screen
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def initialize input, lines: [],
|
32
|
-
name: nil,
|
33
|
-
|
34
|
-
|
33
|
+
name: nil,
|
34
|
+
search: nil,
|
35
|
+
first_line: 0,
|
36
|
+
following_mode: false,
|
37
|
+
line_mode: false,
|
38
|
+
separation_mode: false,
|
39
|
+
time_stamp: nil,
|
40
|
+
ext_input: nil,
|
41
|
+
fifo_file: nil,
|
42
|
+
watch: false,
|
43
|
+
filter_command: nil
|
44
|
+
|
35
45
|
@rs = RenderStatus.new
|
36
46
|
@last_rs = nil
|
37
47
|
@rs.y = first_line
|
@@ -42,18 +52,21 @@ class Screen
|
|
42
52
|
@rs.search = search
|
43
53
|
@rs.wrapping = false
|
44
54
|
@rs.ts_mode = false
|
55
|
+
@rs.separation_mode = separation_mode
|
45
56
|
|
46
57
|
@name = name
|
47
58
|
@filename = @name if @name && File.exist?(@name)
|
59
|
+
@filter_command = @filename && filter_command
|
48
60
|
|
49
61
|
@time_stamp = time_stamp
|
50
62
|
@ext_input = ext_input
|
51
63
|
@fifo_file = fifo_file
|
52
|
-
@separation_mode = separation_mode
|
53
64
|
|
54
65
|
@lines = lines
|
55
66
|
@mode = :screen
|
56
67
|
|
68
|
+
@watch_mode = watch
|
69
|
+
|
57
70
|
@following = following_mode
|
58
71
|
@apos = 0
|
59
72
|
|
@@ -70,11 +83,23 @@ class Screen
|
|
70
83
|
end
|
71
84
|
|
72
85
|
@prev_render = {}
|
86
|
+
input = open_file if @filename
|
73
87
|
@meta = input.respond_to?(:meta) ? input.meta : nil
|
74
|
-
|
75
88
|
read_async input if input
|
76
89
|
end
|
77
90
|
|
91
|
+
def open_file
|
92
|
+
input = open(@filename)
|
93
|
+
@rs.last_lineno = 0
|
94
|
+
|
95
|
+
if @filter_command
|
96
|
+
io = IO.popen("#{@filter_command} #{@filename}", err: '/dev/null')
|
97
|
+
# io.close_write
|
98
|
+
input = io
|
99
|
+
end
|
100
|
+
input
|
101
|
+
end
|
102
|
+
|
78
103
|
def setup_line line
|
79
104
|
line = line.chomp
|
80
105
|
line.instance_variable_set(:@time_stamp, Time.now.strftime('%H:%M:%S')) if @time_stamp
|
@@ -117,7 +142,7 @@ class Screen
|
|
117
142
|
ensure
|
118
143
|
if @filename
|
119
144
|
@file_mtime = File.mtime(@filename)
|
120
|
-
@file_lastpos = input.tell
|
145
|
+
@file_lastpos = input.tell unless @filter_command
|
121
146
|
elsif @fifo_file
|
122
147
|
input = open(@fifo_file)
|
123
148
|
log(input)
|
@@ -184,9 +209,9 @@ class Screen
|
|
184
209
|
|
185
210
|
|
186
211
|
def standout
|
187
|
-
Curses
|
188
|
-
|
189
|
-
|
212
|
+
cattr Curses::A_STANDOUT do
|
213
|
+
yield
|
214
|
+
end
|
190
215
|
end
|
191
216
|
|
192
217
|
def cattr attr
|
@@ -222,11 +247,11 @@ class Screen
|
|
222
247
|
|
223
248
|
Curses.clear
|
224
249
|
|
225
|
-
if @separation_mode && (lines = @lines[self.y ... (self.y + c_lines - 1)])
|
226
|
-
max_cols = []
|
250
|
+
if @rs.separation_mode && (lines = @lines[self.y ... (self.y + c_lines - 1)])
|
251
|
+
@max_cols = [] unless defined? @max_cols
|
227
252
|
lines.each.with_index{|line, ln|
|
228
253
|
line.split("\t").each_with_index{|w, i|
|
229
|
-
max_cols[i] = max_cols[i] ? [max_cols[i], w.size].max : w.size
|
254
|
+
@max_cols[i] = @max_cols[i] ? [@max_cols[i], w.size].max : w.size
|
230
255
|
}
|
231
256
|
}
|
232
257
|
end
|
@@ -273,29 +298,32 @@ class Screen
|
|
273
298
|
|
274
299
|
line = line[self.x, cols] || ''
|
275
300
|
|
276
|
-
if @separation_mode
|
301
|
+
if @rs.separation_mode
|
277
302
|
line = line.split(/\t/).tap{|e|
|
278
|
-
if (max = max_cols.size) > 0
|
303
|
+
if (max = @max_cols.size) > 0
|
279
304
|
# fill empty columns
|
280
305
|
e[max - 1] ||= nil
|
281
306
|
end
|
282
307
|
}.map.with_index{|w, i|
|
283
|
-
"%-#{max_cols[i]}s" % w
|
308
|
+
"%-#{@max_cols[i]}s" % w
|
284
309
|
}.join(' | ')
|
285
310
|
end
|
286
311
|
|
287
|
-
if !@rs.search || !(Regexp === @rs.search)
|
312
|
+
if !@rs.search || !(Regexp === @rs.search) ||
|
313
|
+
(parts = search_partition(line, @rs.search)).is_a?(String)
|
288
314
|
Curses.addstr line
|
289
315
|
else
|
290
|
-
|
291
|
-
|
292
|
-
|
316
|
+
cattr Curses::A_UNDERLINE do
|
317
|
+
parts.each{|(matched, str)|
|
318
|
+
if matched == :match
|
319
|
+
standout{
|
320
|
+
Curses.addstr str
|
321
|
+
}
|
322
|
+
else
|
293
323
|
Curses.addstr str
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
end
|
298
|
-
}
|
324
|
+
end
|
325
|
+
}
|
326
|
+
end
|
299
327
|
end
|
300
328
|
}
|
301
329
|
end
|
@@ -361,17 +389,25 @@ class Screen
|
|
361
389
|
|
362
390
|
def check_update
|
363
391
|
if @loading == false
|
364
|
-
if @filename && File.
|
365
|
-
|
392
|
+
if @filename && File.mtime(@filename) > @file_mtime
|
393
|
+
screen_status "#{@filename} is updated."
|
366
394
|
|
367
|
-
if
|
368
|
-
|
369
|
-
|
370
|
-
|
395
|
+
if @watch_mode
|
396
|
+
@lines = []
|
397
|
+
input = open_file
|
398
|
+
read_async input
|
371
399
|
else
|
372
|
-
input
|
400
|
+
input = open(@filename)
|
401
|
+
|
402
|
+
if input.size < @file_lastpos
|
403
|
+
screen_status "#{@filename} is truncated. Rewinded."
|
404
|
+
pause
|
405
|
+
@lineno = 0
|
406
|
+
else
|
407
|
+
input.seek @file_lastpos
|
408
|
+
end
|
409
|
+
read_async input
|
373
410
|
end
|
374
|
-
read_async input
|
375
411
|
end
|
376
412
|
end
|
377
413
|
end
|
@@ -658,6 +694,9 @@ class Screen
|
|
658
694
|
@rs.line_mode = !@rs.line_mode
|
659
695
|
when 'T'
|
660
696
|
@rs.ts_mode = !@rs.ts_mode if @time_stamp
|
697
|
+
when 'S'
|
698
|
+
@rs.separation_mode = !@rs.separation_mode
|
699
|
+
@max_cols = []
|
661
700
|
when 't'
|
662
701
|
Curses.close_screen
|
663
702
|
@mode = :terminal
|
@@ -828,6 +867,12 @@ class KV
|
|
828
867
|
opts.on('-s', 'Separation mode (tsv)'){
|
829
868
|
@opts[:separation_mode] = true
|
830
869
|
}
|
870
|
+
opts.on('-w', 'Watch mode: Reload on file changed'){
|
871
|
+
@opts[:watch] = true
|
872
|
+
}
|
873
|
+
opts.on('--filter-command=FILTER_COMMAND', 'Apply filter command'){|cmd|
|
874
|
+
@opts[:filter_command] = cmd
|
875
|
+
}
|
831
876
|
opts.parse!(argv)
|
832
877
|
end
|
833
878
|
|
@@ -838,7 +883,7 @@ class KV
|
|
838
883
|
@screens.last.control
|
839
884
|
rescue PopScreen
|
840
885
|
@screens.pop
|
841
|
-
@screens.last.redraw!
|
886
|
+
@screens.last.redraw! unless @screens.empty?
|
842
887
|
rescue PushScreen => e
|
843
888
|
@screens.push e.screen
|
844
889
|
@screens.last.redraw!
|
@@ -861,18 +906,23 @@ def log obj, prefix = ''
|
|
861
906
|
end
|
862
907
|
end
|
863
908
|
|
864
|
-
def
|
909
|
+
def search_partition str, search
|
865
910
|
results = []
|
866
911
|
loop{
|
867
912
|
r = str.match(search){|m|
|
868
913
|
break if m.post_match == str
|
869
|
-
results << [:unmatch, m.pre_match]
|
914
|
+
results << [:unmatch, m.pre_match] unless m.pre_match.empty?
|
870
915
|
results << [:match, m.to_s]
|
871
916
|
str = m.post_match
|
872
917
|
}
|
873
918
|
break unless r
|
874
919
|
}
|
875
|
-
results
|
920
|
+
if results.empty?
|
921
|
+
str
|
922
|
+
else
|
923
|
+
results << [:unmatch, str] unless str.empty?
|
924
|
+
results
|
925
|
+
end
|
876
926
|
end
|
877
927
|
|
878
928
|
def help_io
|
@@ -888,5 +938,5 @@ def help_io
|
|
888
938
|
end
|
889
939
|
}
|
890
940
|
|
891
|
-
|
941
|
+
StringIO.new(help.join)
|
892
942
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Sasada
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -32,6 +32,7 @@ executables:
|
|
32
32
|
extensions: []
|
33
33
|
extra_rdoc_files: []
|
34
34
|
files:
|
35
|
+
- ".github/FUNDING.yml"
|
35
36
|
- ".gitignore"
|
36
37
|
- LICENSE
|
37
38
|
- README.md
|
@@ -61,8 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
62
|
- !ruby/object:Gem::Version
|
62
63
|
version: '0'
|
63
64
|
requirements: []
|
64
|
-
|
65
|
-
rubygems_version: 2.7.6
|
65
|
+
rubygems_version: 3.1.6
|
66
66
|
signing_key:
|
67
67
|
specification_version: 4
|
68
68
|
summary: 'kv: A page viewer written by Ruby'
|