filecon 0.7.0 → 0.7.2
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 -0
- data/bin/filecon +1 -1
- data/filecon.1 +1 -1
- data/lib/filecon/version.rb +1 -1
- data/lib/filecon.rb +33 -14
- 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: 7670630693e1cef53e636d2d81dee3779c0237456647b38962c12bda4bb81274
|
|
4
|
+
data.tar.gz: f2b38e25d2900e372287308d0e9c25a9f1c2e214860d63bd5fffc7891675a553
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 602b4f408a63a6783bc7dfd07131ba1f67d94233e928c5d93051d6c355817e10c83f93b797801cad0f5e083374c494deb3585ed45869c889f947e893ef7286c6
|
|
7
|
+
data.tar.gz: d6b91aa19de3911f71b70d3d528e50d43caa911eb03a879566f19543b9d73a8273ec93bee3e70c0ae5b8775544858f5b753211064cf47726a72f894d51e97a14
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## [vx.y.z] — __DATE__
|
|
4
4
|
|
|
5
|
+
## [v0.7.2] — 2026-10-19
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Recurse (and listing in general) survives filenames with invalid byte sequences — path splitting now works on byte copies and the hidden-file check on scrubbed copies, so a single latin-1 relic no longer kills the whole walk with `invalid byte sequence in UTF-8`; startup history parsing got the same one-word hardening instead of silently discarding all history
|
|
9
|
+
- Same-filesystem `move` renames instead of re-copying — `transfer` tries `File.rename` first (instant, `mv`-style, and it moves symlinks as links), falling back to the rsync copy only across filesystems
|
|
10
|
+
- The `|`-command branch no longer crashes when the command cannot launch (`run` reports the launch failure as its return value, which `dispatch` then tried to read like a stream)
|
|
11
|
+
- The listing refreshes right after a transfer completes, with no keypress: the viewed directory (including a destination reached via the `%dir` pick) is rescanned, the trailing repaint-and-wait steps are gone, and the status line keeps only the tally instead of an echoed command line
|
|
12
|
+
|
|
13
|
+
## [v0.7.1] — 2026-10-13
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Windowed commands with an unlaunchable terminal report on the status line (naming the binary and the `+` config key) instead of failing silently; the terminal is exec'd directly so the OS reports a missing binary
|
|
17
|
+
- `=cmd` output keeps split multibyte characters intact — pipe chunks are byte slices, so a UTF-8 character could arrive in two halves; the streaming loop now buffers trailing high bytes until the character completes (genuinely broken bytes still fall back to replacement), and every emitted span is valid UTF-8
|
|
18
|
+
- Pipe results stay on the status line — the bottom line now shows whatever the last action left until the next keypress restores the bar, so the first line of `|` output remains visible instead of being repainted over immediately
|
|
19
|
+
|
|
5
20
|
## [v0.7.0] — 2026-10-12
|
|
6
21
|
|
|
7
22
|
### Changed
|
data/bin/filecon
CHANGED
|
@@ -22,7 +22,7 @@ begin
|
|
|
22
22
|
|
|
23
23
|
[dh_path, ch_path].each { |f| FileUtils.touch f }
|
|
24
24
|
|
|
25
|
-
parse = ->(p) { File.readlines(p).map { |l| s = l.chomp.split(",", 2); [s[0].to_i, s[1]] } rescue [] }
|
|
25
|
+
parse = ->(p) { File.readlines(p).map { |l| s = l.chomp.scrub.split(",", 2); [s[0].to_i, s[1]] } rescue [] }
|
|
26
26
|
|
|
27
27
|
config = Filecon.load_config(bundled_path, "/etc/filecon/config.yaml", config_path)
|
|
28
28
|
|
data/filecon.1
CHANGED
data/lib/filecon/version.rb
CHANGED
data/lib/filecon.rb
CHANGED
|
@@ -6,6 +6,7 @@ end
|
|
|
6
6
|
|
|
7
7
|
require "fileutils"
|
|
8
8
|
require "find"
|
|
9
|
+
require "shellwords"
|
|
9
10
|
require "yaml"
|
|
10
11
|
require "tempfile"
|
|
11
12
|
|
|
@@ -61,7 +62,7 @@ class Filecon::App < Typr::Browser
|
|
|
61
62
|
def directory
|
|
62
63
|
@directory.is_a?(Array) ? @directory.inject { |a, b|
|
|
63
64
|
common = []
|
|
64
|
-
a.split("/").zip(b.split("/")).each { |x, y|
|
|
65
|
+
a.b.split("/").zip(b.b.split("/")).each { |x, y|
|
|
65
66
|
break if x != y
|
|
66
67
|
common << x
|
|
67
68
|
}
|
|
@@ -77,7 +78,7 @@ class Filecon::App < Typr::Browser
|
|
|
77
78
|
Dir.exist?(d) && File.readable?(d) && File.executable?(d) ? d : nil }
|
|
78
79
|
prefix = dirs.inject { |a, b|
|
|
79
80
|
common = []
|
|
80
|
-
a.split("/").zip(b.split("/")).each { |x, y|
|
|
81
|
+
a.b.split("/").zip(b.b.split("/")).each { |x, y|
|
|
81
82
|
break if x != y
|
|
82
83
|
common << x
|
|
83
84
|
}
|
|
@@ -259,6 +260,8 @@ class Filecon::App < Typr::Browser
|
|
|
259
260
|
if File.directory?( src ) and !File.symlink?( src )
|
|
260
261
|
FileUtils.mkdir_p( dst )
|
|
261
262
|
done += 1
|
|
263
|
+
elsif op == :move and ( File.rename(src, dst) rescue false )
|
|
264
|
+
done += 1
|
|
262
265
|
else
|
|
263
266
|
if @has_rsync.nil?
|
|
264
267
|
begin
|
|
@@ -322,9 +325,8 @@ class Filecon::App < Typr::Browser
|
|
|
322
325
|
colors: { default: @colors[:error], border: @colors[:border] },
|
|
323
326
|
alternate: false).pick(:none)
|
|
324
327
|
end
|
|
325
|
-
show
|
|
326
|
-
|
|
327
|
-
tally
|
|
328
|
+
@user.show tally
|
|
329
|
+
nil
|
|
328
330
|
end
|
|
329
331
|
|
|
330
332
|
def resolve_conflict src, dst
|
|
@@ -397,9 +399,9 @@ class Filecon::App < Typr::Browser
|
|
|
397
399
|
fmt = @prefixes&.[](cmd[0].to_s)
|
|
398
400
|
if fmt
|
|
399
401
|
body = cmd[1..-1]
|
|
400
|
-
body = body.gsub(
|
|
402
|
+
body = body.gsub(/\\|'/, "\\" => "\\\\", "'" => %q{'"'"'}) if fmt =~ /'[^']*%s/
|
|
401
403
|
result = fmt.gsub('%s') { body }
|
|
402
|
-
result.start_with?('!') ? eval(result[1..-1]) :
|
|
404
|
+
result.start_with?('!') ? eval(result[1..-1]) : (IO.popen(Shellwords.split(result), "r", pgroup: true, err: File::NULL) rescue @user.show "#{(t = result.split.first.to_s).start_with?("$") ? "no terminal configured" : "'#{t}' cannot launch"} — set \"+\" prefix in ~/.config/filecon/config.yaml")
|
|
403
405
|
else
|
|
404
406
|
shell(cmd + " 2>&1", "r", in: File::NULL)
|
|
405
407
|
end
|
|
@@ -427,18 +429,33 @@ class Filecon::App < Typr::Browser
|
|
|
427
429
|
text = Text.new(top: 1, right: -1, bottom: -2, header: body, margin: ' ',
|
|
428
430
|
colors: { regex: :generic, border: @colors[:border] }, input: "")
|
|
429
431
|
io = shell("#{body} 2>&1", "r", in: File::NULL)
|
|
432
|
+
pending = +"".b
|
|
430
433
|
begin
|
|
431
434
|
loop do
|
|
432
|
-
|
|
433
|
-
|
|
435
|
+
pending << io.readpartial(4096)
|
|
436
|
+
s = pending.dup.force_encoding(Encoding::UTF_8)
|
|
437
|
+
unless s.valid_encoding?
|
|
438
|
+
cut = pending.bytesize
|
|
439
|
+
cut -= 1 while cut > 0 and pending.getbyte(cut - 1) >= 0x80
|
|
440
|
+
tail, head = pending.byteslice(cut..-1), pending.byteslice(0...cut).force_encoding(Encoding::UTF_8)
|
|
441
|
+
if !tail.empty? and head.valid_encoding?
|
|
442
|
+
s, pending = head, tail
|
|
443
|
+
else
|
|
444
|
+
s, pending = s.scrub, +"".b
|
|
445
|
+
end
|
|
446
|
+
else
|
|
447
|
+
pending = +"".b
|
|
448
|
+
end
|
|
449
|
+
text << s
|
|
434
450
|
text.show
|
|
435
451
|
end
|
|
436
452
|
rescue EOFError
|
|
453
|
+
text << pending.dup.force_encoding(Encoding::UTF_8).scrub unless pending.empty?
|
|
437
454
|
end
|
|
438
455
|
io.close
|
|
439
456
|
text.pick(:none)
|
|
440
457
|
elsif cmd[0] == ?|
|
|
441
|
-
line = io
|
|
458
|
+
line = io&.gets
|
|
442
459
|
if line
|
|
443
460
|
nc, ac = @colors[:commands]
|
|
444
461
|
head = name ? "#{color_code(nc)}#{name}#{color_code(ac)}:" : color_code(nc)
|
|
@@ -453,7 +470,6 @@ class Filecon::App < Typr::Browser
|
|
|
453
470
|
head = name ? "#{color_code(nc)}#{name}#{color_code(ac)}:" : color_code(nc)
|
|
454
471
|
@user.show "> #{head}#{cmd[1..-1]}#{color_code(@colors[:default])} : #{output.lines.last}"
|
|
455
472
|
show
|
|
456
|
-
Typr.read_key
|
|
457
473
|
end
|
|
458
474
|
end
|
|
459
475
|
if io.is_a?(IO) and !io.closed?
|
|
@@ -467,6 +483,10 @@ class Filecon::App < Typr::Browser
|
|
|
467
483
|
end
|
|
468
484
|
Array(id).sort.reverse.each { |i| refresh_row i } if id && cmd[0..2] != '!cd' && @directory == dir
|
|
469
485
|
@selected[:rows] = [] if id && @directory != dir
|
|
486
|
+
if id && cmd[0..2] != '!cd' && @directory != dir
|
|
487
|
+
cd @directory
|
|
488
|
+
sort
|
|
489
|
+
end
|
|
470
490
|
show
|
|
471
491
|
io
|
|
472
492
|
end
|
|
@@ -588,7 +608,7 @@ class Filecon::App < Typr::Browser
|
|
|
588
608
|
return if @directory.is_a?(Array)
|
|
589
609
|
root = File.expand_path(@directory)
|
|
590
610
|
dirs = [root] + Dir.glob("**/*", File::FNM_DOTMATCH, base: root).sort.filter_map { |p|
|
|
591
|
-
next if !@show_hidden && p.split(?/).any? { |c| c.start_with?(?.) }
|
|
611
|
+
next if !@show_hidden && p.scrub.split(?/).any? { |c| c.start_with?(?.) }
|
|
592
612
|
d = File.expand_path(p, root)
|
|
593
613
|
d if File.directory?(d)
|
|
594
614
|
}
|
|
@@ -698,6 +718,7 @@ class Filecon::App < Typr::Browser
|
|
|
698
718
|
show
|
|
699
719
|
draw_hints :rows
|
|
700
720
|
key = Typr.read_key
|
|
721
|
+
@user.reset
|
|
701
722
|
next unless key
|
|
702
723
|
if act = prefixed_binding( key )
|
|
703
724
|
cmd = build act, nil
|
|
@@ -716,14 +737,12 @@ class Filecon::App < Typr::Browser
|
|
|
716
737
|
value = send( key )
|
|
717
738
|
open_file( value, !( key.right? or alt ) ) if value.is_a?( Integer )
|
|
718
739
|
end
|
|
719
|
-
@user.reset
|
|
720
740
|
else
|
|
721
741
|
alt = key.is_a?(String) && key[/\A\e(\d)\z/]
|
|
722
742
|
key = key[1] if alt
|
|
723
743
|
id = send( key )
|
|
724
744
|
id = send( id ) while id.is_a? String
|
|
725
745
|
open_file( id, !alt ) if id.is_a? Integer
|
|
726
|
-
@user.reset
|
|
727
746
|
end
|
|
728
747
|
end
|
|
729
748
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: filecon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.2
|
|
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-19 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: typr
|