Use ASCII_8BIT for paths and directory entries

On Unix systems the encoding of file names is specified by the user via the
locale settings.

In order to avoid encoding problems simply read file names in ASCII 8 bit
encoding and try to convert to the external encoding while replacing undefined
characters.

Also, does not show an icon if the external encoding does not support it and
shows a `=` instead of a check mark for git status.

Fixes #352.
This commit is contained in:
Claudio Bley 2020-04-15 23:04:00 +02:00
parent 7e84eded0c
commit 73e4de9378
9 changed files with 43 additions and 11 deletions

View file

@ -56,6 +56,8 @@ script:
- colorls --color=always
- colorls --tree
- colorls --tree=1
- LC_ALL=C colorls spec/fixtures/
- LC_ALL=C colorls --git spec/fixtures/
deploy:
provider: rubygems

View file

@ -47,7 +47,9 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = '>= 2.4.0'
spec.files = `git ls-files -z`.split("\x0").reject do |f|
spec.files = IO.popen(
%w[git ls-files -z], external_encoding: Encoding::ASCII_8BIT
).read.split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/})
end

View file

@ -72,14 +72,14 @@ module ColorLS
CHARS_PER_ITEM = 12
def item_widths
@contents.map { |item| item.name.size + CHARS_PER_ITEM }
@contents.map { |item| item.show.size + CHARS_PER_ITEM }
end
def init_contents(path)
info = FileInfo.new(path, link_info = @long)
if info.directory?
@contents = Dir.entries(path)
@contents = Dir.entries(path, encoding: Encoding::ASCII_8BIT)
filter_hidden_contents
@ -239,7 +239,11 @@ module ColorLS
end
def git_file_info(path)
return ' ✓ '.colorize(@colors[:unchanged]) unless @git_status[path]
unless @git_status[path]
return ' ✓ '
.encode(Encoding.default_external, undef: :replace, replace: '=')
.colorize(@colors[:unchanged])
end
Git.colored_status_symbols(@git_status[path], @colors)
end
@ -283,10 +287,10 @@ module ColorLS
@count[increment] += 1
value = increment == :folders ? @folders[key] : @files[key]
logo = value.gsub(/\\u[\da-f]{4}/i) { |m| [m[-4..-1].to_i(16)].pack('U') }
name = content.name
name = content.show
name = make_link(path, name) if @hyperlink
name += content.directory? ? '/' : ' '
entry = logo + ' ' + name
entry = logo.encode(Encoding.default_external, undef: :replace, replace: '') + ' ' + name
"#{long_info(content)} #{git_info(content)} #{entry.colorize(color)}#{symlink_info(content)}"
end
@ -295,9 +299,10 @@ module ColorLS
padding = 0
line = +''
chunk.each_with_index do |content, i|
entry = fetch_string(@input, content, *options(content))
line << ' ' * padding
line << ' ' << fetch_string(@input, content, *options(content))
padding = widths[i] - content.name.length - CHARS_PER_ITEM
line << ' ' << entry.encode(Encoding.default_external, undef: :replace)
padding = widths[i] - content.show.length - CHARS_PER_ITEM
end
print line << "\n"
end

View file

@ -16,6 +16,8 @@ module ColorLS
@name = File.basename(path)
@stats = File.lstat(path)
@show_name = nil
handle_symlink(path) if link_info && @stats.symlink?
end
@ -23,6 +25,13 @@ module ColorLS
FileInfo.new(path)
end
def show
return @show_name unless @show_name.nil?
@show_name = @name.encode(Encoding.find('filesystem'), Encoding.default_external,
invalid: :replace, undef: :replace)
end
def dead?
@dead
end

View file

@ -31,7 +31,11 @@ module ColorLS
end
def self.colored_status_symbols(modes, colors)
return ' ✓ '.colorize(colors[:unchanged]) if modes.empty?
if modes.empty?
return ' ✓ '
.encode(Encoding.default_external, undef: :replace, replace: '=')
.colorize(colors[:unchanged])
end
modes = modes.to_a.join.uniq.rjust(3).ljust(4)
@ -51,7 +55,10 @@ module ColorLS
end
def git_subdir_status(repo_path)
yield IO.popen(['git', '-C', repo_path, 'status', '--porcelain', '-z', '-unormal', '--ignored', '.'])
yield IO.popen(
['git', '-C', repo_path, 'status', '--porcelain', '-z', '-unormal', '--ignored', '.'],
external_encoding: Encoding::ASCII_8BIT
)
end
end
end

View file

@ -20,7 +20,7 @@ module ColorLS
end
def read_file(filepath)
::YAML.safe_load(File.read(filepath)).symbolize_keys
::YAML.safe_load(File.read(filepath, encoding: Encoding::UTF_8)).symbolize_keys
end
end
end

View file

@ -68,6 +68,7 @@ RSpec.describe ColorLS::Flags do
:directory? => false,
:owner => "user",
:name => "a.txt",
:show => "a.txt",
:nlink => 1,
:size => 128,
:blockdev? => false,
@ -95,6 +96,7 @@ RSpec.describe ColorLS::Flags do
:directory? => false,
:owner => "user",
:name => "a.txt",
:show => "a.txt",
:nlink => 5, # number of hardlinks
:size => 128,
:blockdev? => false,

View file

@ -1,6 +1,11 @@
require 'spec_helper'
RSpec.describe ColorLS::Git do
before(:all) do
`echo` # initialize $CHILD_STATUS
expect($CHILD_STATUS).to be_success
end
def git_status(*entries)
StringIO.new entries.map { |line| line + "\x0" }.join
end

0
spec/fixtures/Glück vendored Normal file
View file