colorls 1.4.4.pre.846 → 1.4.4.pre.851
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/.rubocop.yml +16 -5
- data/Gemfile +2 -0
- data/Rakefile +4 -4
- data/colorls.gemspec +6 -2
- data/lib/colorls.rb +8 -7
- data/lib/colorls/core.rb +106 -92
- data/lib/colorls/fileinfo.rb +13 -8
- data/lib/colorls/flags.rb +42 -19
- data/lib/colorls/git.rb +33 -24
- data/man/colorls.1 +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10f77d6d62a7eabd60fe2ad90259876e8c264ac39394324308b024da81865074
|
|
4
|
+
data.tar.gz: b64efbf3c5cdfff854c87b653796edd257159b18f8c80c67686b4fdfecb602bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b99aa056b748c5f0342543466dad706653bc42be2c04bd00259661061b1e4d248586780d2bf73b348112b2e66ba73c9e775b6f7495bee497833de2607bd708b7
|
|
7
|
+
data.tar.gz: cbf72ae7c0d52c80a048958fbc8457ef24608f530b78d21b8147297eeeb2b1e5c144a00f0e226e048829b2afe511cb0c8f7fa30bfec1fb6290159a54cf8dea5a
|
data/.rubocop.yml
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
require:
|
|
1
|
+
require:
|
|
2
|
+
- rubocop-performance
|
|
3
|
+
- rubocop-rake
|
|
4
|
+
- rubocop-rspec
|
|
2
5
|
|
|
3
6
|
AllCops:
|
|
4
|
-
Include:
|
|
5
|
-
- 'lib/**/*'
|
|
6
7
|
Exclude:
|
|
7
8
|
- 'vendor/**/*'
|
|
8
9
|
- 'benchmarks/*'
|
|
9
10
|
- 'profile/*'
|
|
10
|
-
- 'lib/yaml/*'
|
|
11
|
-
- 'lib/**/*.sh'
|
|
12
11
|
DisplayCopNames: true
|
|
13
12
|
NewCops: enable
|
|
14
13
|
TargetRubyVersion: 2.5
|
|
@@ -118,3 +117,15 @@ Metrics/PerceivedComplexity:
|
|
|
118
117
|
|
|
119
118
|
Style/Documentation:
|
|
120
119
|
Enabled: false
|
|
120
|
+
|
|
121
|
+
RSpec/NamedSubject:
|
|
122
|
+
Enabled: false
|
|
123
|
+
|
|
124
|
+
RSpec/SubjectStub:
|
|
125
|
+
Enabled: false
|
|
126
|
+
|
|
127
|
+
RSpec/ExampleLength:
|
|
128
|
+
Enabled: false
|
|
129
|
+
|
|
130
|
+
RSpec/ContextWording:
|
|
131
|
+
Enabled: false
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bundler/setup'
|
|
2
4
|
require 'rubygems/tasks'
|
|
3
5
|
Gem::Tasks.new
|
|
4
6
|
|
|
5
7
|
require 'rspec/core/rake_task'
|
|
6
8
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
|
7
|
-
t.rspec_opts =
|
|
9
|
+
t.rspec_opts = '--warnings'
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
require 'rubocop/rake_task'
|
|
11
|
-
RuboCop::RakeTask.new
|
|
12
|
-
task.requires << 'rubocop-rspec'
|
|
13
|
-
end
|
|
13
|
+
RuboCop::RakeTask.new
|
|
14
14
|
|
|
15
15
|
desc 'Build the manual'
|
|
16
16
|
file 'man/colorls.1' => ['man/colorls.1.ronn', 'lib/colorls/flags.rb'] do
|
data/colorls.gemspec
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
5
|
require 'colorls/version'
|
|
@@ -21,7 +23,7 @@ POST_INSTALL_MESSAGE = %(
|
|
|
21
23
|
Man pages have been added. Checkout `man colorls`.
|
|
22
24
|
|
|
23
25
|
*******************************************************************
|
|
24
|
-
)
|
|
26
|
+
)
|
|
25
27
|
|
|
26
28
|
# rubocop:disable Metrics/BlockLength
|
|
27
29
|
Gem::Specification.new do |spec|
|
|
@@ -47,7 +49,7 @@ Gem::Specification.new do |spec|
|
|
|
47
49
|
|
|
48
50
|
spec.required_ruby_version = '>= 2.5.0'
|
|
49
51
|
|
|
50
|
-
spec.files
|
|
52
|
+
spec.files = IO.popen(
|
|
51
53
|
%w[git ls-files -z], external_encoding: Encoding::ASCII_8BIT
|
|
52
54
|
).read.split("\x0").reject do |f|
|
|
53
55
|
f.match(%r{^(test|spec|features)/})
|
|
@@ -59,6 +61,7 @@ Gem::Specification.new do |spec|
|
|
|
59
61
|
|
|
60
62
|
spec.post_install_message = POST_INSTALL_MESSAGE
|
|
61
63
|
|
|
64
|
+
spec.add_runtime_dependency 'addressable', '~> 2.7'
|
|
62
65
|
spec.add_runtime_dependency 'clocale', '~> 0'
|
|
63
66
|
spec.add_runtime_dependency 'filesize', '~> 0'
|
|
64
67
|
spec.add_runtime_dependency 'manpages', '~> 0'
|
|
@@ -75,6 +78,7 @@ Gem::Specification.new do |spec|
|
|
|
75
78
|
spec.add_development_dependency 'rspec-its', '~> 1.2'
|
|
76
79
|
spec.add_development_dependency 'rubocop', '~> 1.8.0'
|
|
77
80
|
spec.add_development_dependency 'rubocop-performance', '~> 1.9.0'
|
|
81
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0.5'
|
|
78
82
|
spec.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
|
79
83
|
spec.add_development_dependency 'rubygems-tasks', '~> 0'
|
|
80
84
|
spec.add_development_dependency 'simplecov', '~> 0.20.0'
|
data/lib/colorls.rb
CHANGED
|
@@ -8,11 +8,12 @@ require 'io/console'
|
|
|
8
8
|
require 'rainbow/ext/string'
|
|
9
9
|
require 'clocale'
|
|
10
10
|
require 'unicode/display_width'
|
|
11
|
+
require 'addressable/uri'
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
require_relative 'colorls/core'
|
|
14
|
+
require_relative 'colorls/fileinfo'
|
|
15
|
+
require_relative 'colorls/flags'
|
|
16
|
+
require_relative 'colorls/layout'
|
|
17
|
+
require_relative 'colorls/yaml'
|
|
18
|
+
require_relative 'colorls/monkeys'
|
|
19
|
+
require_relative 'colorls/git'
|
data/lib/colorls/core.rb
CHANGED
|
@@ -8,16 +8,21 @@ module ColorLS
|
|
|
8
8
|
@file_encoding
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
@screen_width = IO.console.winsize[1]
|
|
12
|
+
@screen_width = 80 if @screen_width.zero?
|
|
13
|
+
|
|
14
|
+
def self.screen_width
|
|
15
|
+
@screen_width
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
class Core
|
|
12
|
-
def initialize(
|
|
19
|
+
def initialize(all: false, sort: false, show: false,
|
|
13
20
|
mode: nil, git_status: false, almost_all: false, colors: [], group: nil,
|
|
14
21
|
reverse: false, hyperlink: false, tree_depth: nil, show_group: true, show_user: true)
|
|
15
|
-
@
|
|
16
|
-
@count = {folders: 0, recognized_files: 0, unrecognized_files: 0}
|
|
22
|
+
@count = {folders: 0, recognized_files: 0, unrecognized_files: 0}
|
|
17
23
|
@all = all
|
|
18
24
|
@almost_all = almost_all
|
|
19
25
|
@hyperlink = hyperlink
|
|
20
|
-
@report = report
|
|
21
26
|
@sort = sort
|
|
22
27
|
@reverse = reverse
|
|
23
28
|
@group = group
|
|
@@ -26,42 +31,68 @@ module ColorLS
|
|
|
26
31
|
init_long_format(mode,show_group,show_user)
|
|
27
32
|
@tree = {mode: mode == :tree, depth: tree_depth}
|
|
28
33
|
@horizontal = mode == :horizontal
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@screen_width = IO.console.winsize[1]
|
|
32
|
-
@screen_width = 80 if @screen_width.zero?
|
|
34
|
+
@git_status = init_git_status(git_status)
|
|
33
35
|
|
|
34
36
|
init_colors colors
|
|
35
37
|
|
|
36
|
-
@contents = init_contents(@input)
|
|
37
38
|
init_icons
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
def
|
|
41
|
+
def ls_dir(info)
|
|
42
|
+
if @tree[:mode]
|
|
43
|
+
print "\n"
|
|
44
|
+
return tree_traverse(info.path, 0, 1, 2)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@contents = Dir.entries(info.path, encoding: ColorLS.file_encoding)
|
|
48
|
+
|
|
49
|
+
filter_hidden_contents
|
|
50
|
+
|
|
51
|
+
@contents.map! { |e| FileInfo.dir_entry(info.path, e, link_info: @long) }
|
|
52
|
+
|
|
53
|
+
filter_contents if @show
|
|
54
|
+
sort_contents if @sort
|
|
55
|
+
group_contents if @group
|
|
56
|
+
|
|
41
57
|
return print "\n Nothing to show here\n".colorize(@colors[:empty]) if @contents.empty?
|
|
42
58
|
|
|
59
|
+
ls
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def ls_files(files)
|
|
63
|
+
@contents = files
|
|
64
|
+
|
|
65
|
+
ls
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def display_report
|
|
69
|
+
print "\n Found #{@count.values.sum} items in total.".colorize(@colors[:report])
|
|
70
|
+
|
|
71
|
+
puts "\n\n\tFolders\t\t\t: #{@count[:folders]}"\
|
|
72
|
+
"\n\tRecognized files\t: #{@count[:recognized_files]}"\
|
|
73
|
+
"\n\tUnrecognized files\t: #{@count[:unrecognized_files]}"
|
|
74
|
+
.colorize(@colors[:report])
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def ls
|
|
80
|
+
init_column_lengths
|
|
81
|
+
|
|
43
82
|
layout = case
|
|
44
|
-
when @tree[:mode]
|
|
45
|
-
print "\n"
|
|
46
|
-
return tree_traverse(@input, 0, 1, 2)
|
|
47
83
|
when @horizontal
|
|
48
|
-
HorizontalLayout.new(@contents, item_widths,
|
|
84
|
+
HorizontalLayout.new(@contents, item_widths, ColorLS.screen_width)
|
|
49
85
|
when @one_per_line || @long
|
|
50
86
|
SingleColumnLayout.new(@contents)
|
|
51
87
|
else
|
|
52
|
-
VerticalLayout.new(@contents, item_widths,
|
|
88
|
+
VerticalLayout.new(@contents, item_widths, ColorLS.screen_width)
|
|
53
89
|
end
|
|
54
90
|
|
|
55
91
|
layout.each_line do |line, widths|
|
|
56
92
|
ls_line(line, widths)
|
|
57
93
|
end
|
|
58
|
-
|
|
59
|
-
display_report if @report
|
|
60
|
-
true
|
|
61
94
|
end
|
|
62
95
|
|
|
63
|
-
private
|
|
64
|
-
|
|
65
96
|
def init_colors(colors)
|
|
66
97
|
@colors = colors
|
|
67
98
|
@modes = Hash.new do |hash, key|
|
|
@@ -75,12 +106,26 @@ module ColorLS
|
|
|
75
106
|
end
|
|
76
107
|
end
|
|
77
108
|
|
|
78
|
-
def init_long_format(mode,show_group,show_user)
|
|
109
|
+
def init_long_format(mode, show_group, show_user)
|
|
79
110
|
@long = mode == :long
|
|
80
111
|
@show_group = show_group
|
|
81
112
|
@show_user = show_user
|
|
82
113
|
end
|
|
83
114
|
|
|
115
|
+
def init_git_status(show_git)
|
|
116
|
+
return {}.freeze unless show_git
|
|
117
|
+
|
|
118
|
+
# stores git status information per directory
|
|
119
|
+
Hash.new do |hash, key|
|
|
120
|
+
path = File.absolute_path key.parent
|
|
121
|
+
if hash.key? path
|
|
122
|
+
hash[path]
|
|
123
|
+
else
|
|
124
|
+
hash[path] = Git.status(path)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
84
129
|
# how much characters an item occupies besides its name
|
|
85
130
|
CHARS_PER_ITEM = 12
|
|
86
131
|
|
|
@@ -88,29 +133,6 @@ module ColorLS
|
|
|
88
133
|
@contents.map { |item| Unicode::DisplayWidth.of(item.show) + CHARS_PER_ITEM }
|
|
89
134
|
end
|
|
90
135
|
|
|
91
|
-
def init_contents(path)
|
|
92
|
-
info = FileInfo.new(path, link_info: @long)
|
|
93
|
-
|
|
94
|
-
if info.directory?
|
|
95
|
-
@contents = Dir.entries(path, encoding: ColorLS.file_encoding)
|
|
96
|
-
|
|
97
|
-
filter_hidden_contents
|
|
98
|
-
|
|
99
|
-
@contents.map! { |e| FileInfo.new(File.join(path, e), link_info: @long) }
|
|
100
|
-
|
|
101
|
-
filter_contents if @show
|
|
102
|
-
sort_contents if @sort
|
|
103
|
-
group_contents if @group
|
|
104
|
-
else
|
|
105
|
-
@contents = [info]
|
|
106
|
-
end
|
|
107
|
-
@total_content_length = @contents.length
|
|
108
|
-
|
|
109
|
-
init_column_lengths
|
|
110
|
-
|
|
111
|
-
@contents
|
|
112
|
-
end
|
|
113
|
-
|
|
114
136
|
def filter_hidden_contents
|
|
115
137
|
@contents -= %w[. ..] unless @all
|
|
116
138
|
@contents.keep_if { |x| !x.start_with? '.' } unless @all || @almost_all
|
|
@@ -175,18 +197,6 @@ module ColorLS
|
|
|
175
197
|
@folder_aliases = ColorLS::Yaml.new('folder_aliases.yaml').load(aliase: true)
|
|
176
198
|
end
|
|
177
199
|
|
|
178
|
-
def display_report
|
|
179
|
-
print "\n Found #{@total_content_length} contents in directory "
|
|
180
|
-
.colorize(@colors[:report])
|
|
181
|
-
|
|
182
|
-
print File.expand_path(@input).to_s.colorize(@colors[:dir])
|
|
183
|
-
|
|
184
|
-
puts "\n\n\tFolders\t\t\t: #{@count[:folders]}"\
|
|
185
|
-
"\n\tRecognized files\t: #{@count[:recognized_files]}"\
|
|
186
|
-
"\n\tUnrecognized files\t: #{@count[:unrecognized_files]}"
|
|
187
|
-
.colorize(@colors[:report])
|
|
188
|
-
end
|
|
189
|
-
|
|
190
200
|
def format_mode(rwx, special, char)
|
|
191
201
|
m_r = (rwx & 4).zero? ? '-' : 'r'
|
|
192
202
|
m_w = (rwx & 2).zero? ? '-' : 'w'
|
|
@@ -233,42 +243,32 @@ module ColorLS
|
|
|
233
243
|
mtime.colorize(@colors[:no_modifier])
|
|
234
244
|
end
|
|
235
245
|
|
|
236
|
-
def process_git_status_details(git_status)
|
|
237
|
-
@git_status = case
|
|
238
|
-
when !git_status then nil
|
|
239
|
-
when File.directory?(@input) then Git.status(@input)
|
|
240
|
-
else Git.status(File.dirname(@input))
|
|
241
|
-
end
|
|
242
|
-
end
|
|
243
|
-
|
|
244
246
|
def git_info(content)
|
|
245
|
-
return '' unless @git_status
|
|
247
|
+
return '' unless (status = @git_status[content])
|
|
246
248
|
|
|
247
249
|
if content.directory?
|
|
248
|
-
git_dir_info(content
|
|
250
|
+
git_dir_info(content, status)
|
|
249
251
|
else
|
|
250
|
-
git_file_info(content.name)
|
|
252
|
+
git_file_info(status[content.name])
|
|
251
253
|
end
|
|
252
254
|
end
|
|
253
255
|
|
|
254
|
-
def git_file_info(
|
|
255
|
-
|
|
256
|
-
return ' ✓ '
|
|
257
|
-
.encode(Encoding.default_external, undef: :replace, replace: '=')
|
|
258
|
-
.colorize(@colors[:unchanged])
|
|
259
|
-
end
|
|
256
|
+
def git_file_info(status)
|
|
257
|
+
return Git.colored_status_symbols(status, @colors) if status
|
|
260
258
|
|
|
261
|
-
|
|
259
|
+
' ✓ '
|
|
260
|
+
.encode(Encoding.default_external, undef: :replace, replace: '=')
|
|
261
|
+
.colorize(@colors[:unchanged])
|
|
262
262
|
end
|
|
263
263
|
|
|
264
|
-
def git_dir_info(
|
|
265
|
-
modes = if path == '.'
|
|
266
|
-
Set.new(
|
|
264
|
+
def git_dir_info(content, status)
|
|
265
|
+
modes = if content.path == '.'
|
|
266
|
+
Set.new(status.values).flatten
|
|
267
267
|
else
|
|
268
|
-
|
|
268
|
+
status[content.name]
|
|
269
269
|
end
|
|
270
270
|
|
|
271
|
-
if modes.empty? && Dir.empty?(
|
|
271
|
+
if modes.empty? && Dir.empty?(content.path)
|
|
272
272
|
' '
|
|
273
273
|
else
|
|
274
274
|
Git.colored_status_symbols(modes, @colors)
|
|
@@ -303,12 +303,12 @@ module ColorLS
|
|
|
303
303
|
str.encode(Encoding.default_external, undef: :replace, replace: '')
|
|
304
304
|
end
|
|
305
305
|
|
|
306
|
-
def fetch_string(
|
|
306
|
+
def fetch_string(content, key, color, increment)
|
|
307
307
|
@count[increment] += 1
|
|
308
308
|
value = increment == :folders ? @folders[key] : @files[key]
|
|
309
309
|
logo = value.gsub(/\\u[\da-f]{4}/i) { |m| [m[-4..-1].to_i(16)].pack('U') }
|
|
310
310
|
name = content.show
|
|
311
|
-
name = make_link(
|
|
311
|
+
name = make_link(content) if @hyperlink
|
|
312
312
|
name += content.directory? ? '/' : ' '
|
|
313
313
|
entry = "#{out_encode(logo)} #{out_encode(name)}"
|
|
314
314
|
entry = entry.bright if !content.directory? && content.executable?
|
|
@@ -320,7 +320,7 @@ module ColorLS
|
|
|
320
320
|
padding = 0
|
|
321
321
|
line = +''
|
|
322
322
|
chunk.each_with_index do |content, i|
|
|
323
|
-
entry = fetch_string(
|
|
323
|
+
entry = fetch_string(content, *options(content))
|
|
324
324
|
line << ' ' * padding
|
|
325
325
|
line << ' ' << entry.encode(Encoding.default_external, undef: :replace)
|
|
326
326
|
padding = widths[i] - Unicode::DisplayWidth.of(content.show) - CHARS_PER_ITEM
|
|
@@ -330,11 +330,11 @@ module ColorLS
|
|
|
330
330
|
|
|
331
331
|
def file_color(file, key)
|
|
332
332
|
color_key = case
|
|
333
|
-
when file.chardev?
|
|
334
|
-
when file.blockdev?
|
|
335
|
-
when file.socket?
|
|
336
|
-
|
|
337
|
-
|
|
333
|
+
when file.chardev? then :chardev
|
|
334
|
+
when file.blockdev? then :blockdev
|
|
335
|
+
when file.socket? then :socket
|
|
336
|
+
when @files.key?(key) then :recognized_file
|
|
337
|
+
else :unrecognized_file
|
|
338
338
|
end
|
|
339
339
|
@colors[color_key]
|
|
340
340
|
end
|
|
@@ -357,12 +357,26 @@ module ColorLS
|
|
|
357
357
|
[key, color, group]
|
|
358
358
|
end
|
|
359
359
|
|
|
360
|
+
def tree_contents(path)
|
|
361
|
+
@contents = Dir.entries(path, encoding: ColorLS.file_encoding)
|
|
362
|
+
|
|
363
|
+
filter_hidden_contents
|
|
364
|
+
|
|
365
|
+
@contents.map! { |e| FileInfo.dir_entry(path, e, link_info: @long) }
|
|
366
|
+
|
|
367
|
+
filter_contents if @show
|
|
368
|
+
sort_contents if @sort
|
|
369
|
+
group_contents if @group
|
|
370
|
+
|
|
371
|
+
@contents
|
|
372
|
+
end
|
|
373
|
+
|
|
360
374
|
def tree_traverse(path, prespace, depth, indent)
|
|
361
|
-
contents =
|
|
375
|
+
contents = tree_contents(path)
|
|
362
376
|
contents.each do |content|
|
|
363
377
|
icon = content == contents.last || content.directory? ? ' └──' : ' ├──'
|
|
364
378
|
print tree_branch_preprint(prespace, indent, icon).colorize(@colors[:tree])
|
|
365
|
-
print " #{fetch_string(
|
|
379
|
+
print " #{fetch_string(content, *options(content))} \n"
|
|
366
380
|
next unless content.directory?
|
|
367
381
|
|
|
368
382
|
tree_traverse("#{path}/#{content}", prespace + indent, depth + 1, indent) if keep_going(depth)
|
|
@@ -379,9 +393,9 @@ module ColorLS
|
|
|
379
393
|
' │ ' * (prespace/indent) + prespace_icon + '─' * indent
|
|
380
394
|
end
|
|
381
395
|
|
|
382
|
-
def make_link(
|
|
383
|
-
|
|
384
|
-
"\033]8;;#{
|
|
396
|
+
def make_link(content)
|
|
397
|
+
uri = Addressable::URI.convert_path(File.absolute_path(content.path))
|
|
398
|
+
"\033]8;;#{uri}\007#{content.name}\033]8;;\007"
|
|
385
399
|
end
|
|
386
400
|
end
|
|
387
401
|
end
|
data/lib/colorls/fileinfo.rb
CHANGED
|
@@ -9,19 +9,24 @@ module ColorLS
|
|
|
9
9
|
@@users = {} # rubocop:disable Style/ClassVars
|
|
10
10
|
@@groups = {} # rubocop:disable Style/ClassVars
|
|
11
11
|
|
|
12
|
-
attr_reader :stats, :name
|
|
13
|
-
|
|
14
|
-
def initialize(path, link_info: true)
|
|
15
|
-
@name = File.basename(path)
|
|
16
|
-
@stats = File.lstat(path)
|
|
12
|
+
attr_reader :stats, :name, :path, :parent
|
|
17
13
|
|
|
14
|
+
def initialize(name:, parent:, path: nil, link_info: true)
|
|
15
|
+
@name = name
|
|
16
|
+
@parent = parent
|
|
17
|
+
@path = path.nil? ? File.join(parent, name) : path
|
|
18
|
+
@stats = File.lstat(@path)
|
|
18
19
|
@show_name = nil
|
|
19
20
|
|
|
20
|
-
handle_symlink(path) if link_info && @stats.symlink?
|
|
21
|
+
handle_symlink(@path) if link_info && @stats.symlink?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.info(path, link_info: true)
|
|
25
|
+
FileInfo.new(name: File.basename(path), parent: File.dirname(path), path: path, link_info: link_info)
|
|
21
26
|
end
|
|
22
27
|
|
|
23
|
-
def self.
|
|
24
|
-
FileInfo.new(
|
|
28
|
+
def self.dir_entry(dir, child, link_info: true)
|
|
29
|
+
FileInfo.new(name: child, parent: dir, link_info: link_info)
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
def show
|
data/lib/colorls/flags.rb
CHANGED
|
@@ -11,6 +11,8 @@ module ColorLS
|
|
|
11
11
|
@light_colors = false
|
|
12
12
|
|
|
13
13
|
@opts = default_opts
|
|
14
|
+
@show_report = false
|
|
15
|
+
@exit_status_code = 0
|
|
14
16
|
|
|
15
17
|
parse_options
|
|
16
18
|
|
|
@@ -19,30 +21,14 @@ module ColorLS
|
|
|
19
21
|
# FIXME: `--all` and `--tree` do not work together, use `--almost-all` instead
|
|
20
22
|
@opts[:almost_all] = true if @opts[:all]
|
|
21
23
|
@opts[:all] = false
|
|
22
|
-
|
|
23
|
-
# `--tree` does not support reports
|
|
24
|
-
@opts[:report] = false
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def process
|
|
28
27
|
init_locale
|
|
29
28
|
|
|
30
29
|
@args = ['.'] if @args.empty?
|
|
31
|
-
exit_status_code = 0
|
|
32
|
-
@args.sort!.each_with_index do |path, i|
|
|
33
|
-
unless File.exist?(path)
|
|
34
|
-
$stderr.puts "\n Specified path '#{path}' doesn't exist.".colorize(:red)
|
|
35
|
-
exit_status_code = 2
|
|
36
|
-
next
|
|
37
|
-
end
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
puts "\n#{path}:" if Dir.exist?(path) && @args.size > 1
|
|
41
|
-
Core.new(path, **@opts).ls
|
|
42
|
-
rescue SystemCallError => e
|
|
43
|
-
$stderr.puts "#{path}: #{e}".colorize(:red)
|
|
44
|
-
end
|
|
45
|
-
exit_status_code
|
|
31
|
+
process_args
|
|
46
32
|
end
|
|
47
33
|
|
|
48
34
|
def options
|
|
@@ -69,6 +55,44 @@ module ColorLS
|
|
|
69
55
|
warn "WARN: #{e}, check your locale settings"
|
|
70
56
|
end
|
|
71
57
|
|
|
58
|
+
def group_files_and_directories
|
|
59
|
+
infos = @args.flat_map do |arg|
|
|
60
|
+
FileInfo.info(arg)
|
|
61
|
+
rescue Errno::ENOENT
|
|
62
|
+
$stderr.puts "colorls: Specified path '#{arg}' doesn't exist.".colorize(:red)
|
|
63
|
+
@exit_status_code = 2
|
|
64
|
+
[]
|
|
65
|
+
rescue SystemCallError => e
|
|
66
|
+
$stderr.puts "#{path}: #{e}".colorize(:red)
|
|
67
|
+
@exit_status_code = 2
|
|
68
|
+
[]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
infos.group_by(&:directory?).values_at(true, false)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def process_args
|
|
75
|
+
core = Core.new(**@opts)
|
|
76
|
+
|
|
77
|
+
directories, files = group_files_and_directories
|
|
78
|
+
|
|
79
|
+
core.ls_files(files) unless files.nil?
|
|
80
|
+
|
|
81
|
+
directories&.sort_by! do |a|
|
|
82
|
+
CLocale.strxfrm(a.name)
|
|
83
|
+
end&.each do |dir|
|
|
84
|
+
puts "\n#{dir.show}:" if @args.size > 1
|
|
85
|
+
|
|
86
|
+
core.ls_dir(dir)
|
|
87
|
+
rescue SystemCallError => e
|
|
88
|
+
$stderr.puts "#{dir}: #{e}".colorize(:red)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
core.display_report if @show_report
|
|
92
|
+
|
|
93
|
+
@exit_status_code
|
|
94
|
+
end
|
|
95
|
+
|
|
72
96
|
def default_opts
|
|
73
97
|
{
|
|
74
98
|
show: false,
|
|
@@ -78,7 +102,6 @@ module ColorLS
|
|
|
78
102
|
mode: STDOUT.tty? ? :vertical : :one_per_line, # rubocop:disable Style/GlobalStdStream
|
|
79
103
|
all: false,
|
|
80
104
|
almost_all: false,
|
|
81
|
-
report: false,
|
|
82
105
|
git_status: false,
|
|
83
106
|
colors: [],
|
|
84
107
|
tree_depth: 3,
|
|
@@ -117,7 +140,7 @@ module ColorLS
|
|
|
117
140
|
options.on('-d', '--dirs', 'show only directories') { @opts[:show] = :dirs }
|
|
118
141
|
options.on('-f', '--files', 'show only files') { @opts[:show] = :files }
|
|
119
142
|
options.on('--gs', '--git-status', 'show git status for each file') { @opts[:git_status] = true }
|
|
120
|
-
options.on('--report', 'show brief report') { @
|
|
143
|
+
options.on('--report', 'show brief report') { @show_report = true }
|
|
121
144
|
end
|
|
122
145
|
|
|
123
146
|
def add_format_options(options)
|
data/lib/colorls/git.rb
CHANGED
|
@@ -6,29 +6,27 @@ require 'set'
|
|
|
6
6
|
module ColorLS
|
|
7
7
|
module Git
|
|
8
8
|
def self.status(repo_path)
|
|
9
|
-
prefix = git_prefix(repo_path)
|
|
9
|
+
prefix, success = git_prefix(repo_path)
|
|
10
10
|
|
|
11
|
-
return unless
|
|
11
|
+
return unless success
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
prefix_path = Pathname.new(prefix)
|
|
14
14
|
|
|
15
15
|
git_status = Hash.new { |hash, key| hash[key] = Set.new }
|
|
16
16
|
|
|
17
|
-
git_subdir_status(repo_path) do |
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
path = Pathname.new(file).relative_path_from(
|
|
22
|
-
|
|
17
|
+
git_subdir_status(repo_path) do |mode, file|
|
|
18
|
+
if file == prefix
|
|
19
|
+
git_status.default = Set[mode].freeze
|
|
20
|
+
else
|
|
21
|
+
path = Pathname.new(file).relative_path_from(prefix_path)
|
|
23
22
|
git_status[path.descend.first.cleanpath.to_s].add(mode)
|
|
24
|
-
|
|
25
|
-
# skip the next \x0 separated original path for renames, issue #185
|
|
26
|
-
output.gets("\x0") if mode.start_with? 'R'
|
|
27
23
|
end
|
|
28
24
|
end
|
|
25
|
+
|
|
29
26
|
warn "git status failed in #{repo_path}" unless $CHILD_STATUS.success?
|
|
30
27
|
|
|
31
|
-
git_status
|
|
28
|
+
git_status.default = Set.new.freeze if git_status.default.nil?
|
|
29
|
+
git_status.freeze
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
def self.colored_status_symbols(modes, colors)
|
|
@@ -38,28 +36,39 @@ module ColorLS
|
|
|
38
36
|
.colorize(colors[:unchanged])
|
|
39
37
|
end
|
|
40
38
|
|
|
41
|
-
modes
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.gsub('M', 'M'.colorize(colors[:modification]))
|
|
47
|
-
.gsub('D', 'D'.colorize(colors[:deletion]))
|
|
48
|
-
.tr('!', ' ')
|
|
39
|
+
modes.to_a.join.uniq.delete('!').rjust(3).ljust(4)
|
|
40
|
+
.sub('?', '?'.colorize(colors[:untracked]))
|
|
41
|
+
.sub('A', 'A'.colorize(colors[:addition]))
|
|
42
|
+
.sub('M', 'M'.colorize(colors[:modification]))
|
|
43
|
+
.sub('D', 'D'.colorize(colors[:deletion]))
|
|
49
44
|
end
|
|
50
45
|
|
|
51
46
|
class << self
|
|
52
47
|
private
|
|
53
48
|
|
|
54
49
|
def git_prefix(repo_path)
|
|
55
|
-
|
|
50
|
+
[
|
|
51
|
+
IO.popen(['git', '-C', repo_path, 'rev-parse', '--show-prefix'], err: :close, &:gets)&.chomp,
|
|
52
|
+
$CHILD_STATUS.success?
|
|
53
|
+
]
|
|
54
|
+
rescue Errno::ENOENT
|
|
55
|
+
[nil, false]
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def git_subdir_status(repo_path)
|
|
59
|
-
|
|
59
|
+
IO.popen(
|
|
60
60
|
['git', '-C', repo_path, 'status', '--porcelain', '-z', '-unormal', '--ignored', '.'],
|
|
61
61
|
external_encoding: Encoding::ASCII_8BIT
|
|
62
|
-
)
|
|
62
|
+
) do |output|
|
|
63
|
+
while (status_line = output.gets "\x0")
|
|
64
|
+
mode, file = status_line.chomp("\x0").split(' ', 2)
|
|
65
|
+
|
|
66
|
+
yield mode, file
|
|
67
|
+
|
|
68
|
+
# skip the next \x0 separated original path for renames, issue #185
|
|
69
|
+
output.gets("\x0") if mode.start_with? 'R'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
63
72
|
end
|
|
64
73
|
end
|
|
65
74
|
end
|
data/man/colorls.1
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
|
3
3
|
.
|
|
4
|
-
.TH "COLORLS" "1" "
|
|
4
|
+
.TH "COLORLS" "1" "December 2020" "colorls 1.4.3" "colorls Manual"
|
|
5
5
|
.
|
|
6
6
|
.SH "NAME"
|
|
7
7
|
\fBcolorls\fR \- list directory contents with colors and icons
|
metadata
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: colorls
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.4.pre.
|
|
4
|
+
version: 1.4.4.pre.851
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Athitya Kumar
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-01-
|
|
11
|
+
date: 2021-01-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: addressable
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.7'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.7'
|
|
13
27
|
- !ruby/object:Gem::Dependency
|
|
14
28
|
name: clocale
|
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -226,6 +240,20 @@ dependencies:
|
|
|
226
240
|
- - "~>"
|
|
227
241
|
- !ruby/object:Gem::Version
|
|
228
242
|
version: 1.9.0
|
|
243
|
+
- !ruby/object:Gem::Dependency
|
|
244
|
+
name: rubocop-rake
|
|
245
|
+
requirement: !ruby/object:Gem::Requirement
|
|
246
|
+
requirements:
|
|
247
|
+
- - "~>"
|
|
248
|
+
- !ruby/object:Gem::Version
|
|
249
|
+
version: '0.5'
|
|
250
|
+
type: :development
|
|
251
|
+
prerelease: false
|
|
252
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
253
|
+
requirements:
|
|
254
|
+
- - "~>"
|
|
255
|
+
- !ruby/object:Gem::Version
|
|
256
|
+
version: '0.5'
|
|
229
257
|
- !ruby/object:Gem::Dependency
|
|
230
258
|
name: rubocop-rspec
|
|
231
259
|
requirement: !ruby/object:Gem::Requirement
|