colorls 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f4071319ab261196949f1a3cf87ebe1c55d7582c
4
- data.tar.gz: 40c07660304acb180e356b0bfaa4e7ecb6bbe2fc
3
+ metadata.gz: baadf69e664b9bab7c78f96af16d833f7d03302c
4
+ data.tar.gz: e72d0b65aefd804aec27dab9865fb9066e9c56d1
5
5
  SHA512:
6
- metadata.gz: fcacb48be3c568c7cc64815de3847c7b093950f4d834de0b55e9c969aaf791fa0d6fb7547bf347f7211872f5b9c14f035ae7044c64496d0a55c02a85c327cbed
7
- data.tar.gz: edca7e18cef76348a81313431016de823b83b3f79d3579890db0bd0329605f53ee0c7e2c97a46fdfb9b9873e2a5c674801c5d03eba8e6dda2302bb20c45fcbf8
6
+ metadata.gz: 5234ec2b037d9b50f82eac2cfdec97b0befc6f25f563fecd55a25b0f312b6b54acfe9ff573c73a636e6902b2e08dfba8cdff8d89e41182733d9d700a1b07ba10
7
+ data.tar.gz: b6d1d437c80186e03850a8c184892b78cf98ecd261ac41820033a294e3899a671eb0b0d96f4fccdfa6322149653945cd3f9f64ee65611353e80ad9f9e4983eb9
@@ -11,6 +11,7 @@ AllCops:
11
11
  TargetRubyVersion: 2.1
12
12
 
13
13
  # Preferred codebase style ---------------------------------------------
14
+
14
15
  Layout/ExtraSpacing:
15
16
  AllowForAlignment: true
16
17
 
@@ -46,7 +47,7 @@ Metrics/ModuleLength:
46
47
  Max: 200
47
48
 
48
49
  Metrics/ClassLength:
49
- Max: 300
50
+ Max: 350
50
51
 
51
52
  Metrics/ParameterLists:
52
53
  Max: 15
@@ -6,6 +6,7 @@ rvm:
6
6
  - '2.2'
7
7
  - '2.3.0'
8
8
  - '2.4.0'
9
+ - '2.5.0'
9
10
 
10
11
  script:
11
12
  - bundle exec rubocop
@@ -25,6 +26,11 @@ script:
25
26
  - colorls --sd
26
27
  - colorls --sf
27
28
  - colorls -t
29
+ - colorls --sort=time
30
+ - colorls -U
31
+ - colorls --sort=none
32
+ - colorls -S
33
+ - colorls --sort=size
28
34
  - colorls -h
29
35
  - colorls --gs
30
36
  - colorls spec/fixtures/symlinks
@@ -7,7 +7,7 @@ Before sending a Pull Request, please make sure that you're assigned the task on
7
7
  - If a relevant issue already exists, discuss on the issue and get it assigned to yourself on GitHub.
8
8
  - If no relevant issue exists, open a new issue and get it assigned to yourself on GitHub.
9
9
 
10
- Please proceed with a Pull Request only after you're assigned. It'd be sad if your Pull Request (and your hardwork) isn't accepted just because it isn't idealogically compatible.
10
+ Please proceed with a Pull Request only after you're assigned. It'd be sad if your Pull Request (and your hardwork) isn't accepted just because it isn't ideologically compatible.
11
11
 
12
12
  # Developing the gem
13
13
 
data/README.md CHANGED
@@ -6,16 +6,31 @@
6
6
  [![Gem Version](https://badge.fury.io/rb/colorls.svg)](https://badge.fury.io/rb/colorls)
7
7
  [![Build Status](https://travis-ci.org/athityakumar/colorls.svg?branch=master)](https://travis-ci.org/athityakumar/colorls)
8
8
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=shields)](http://makeapullrequest.com)
9
+ [![Stories in Ready](https://badge.waffle.io/athityakumar/colorls.png?label=next)](https://waffle.io/athityakumar/colorls?utm_source=badge)
9
10
 
10
11
  A Ruby script that colorizes the `ls` output with color and icons. Here are the screenshots of working example on an iTerm2 terminal (Mac OS), `oh-my-zsh` with `powerlevel9k` theme and `powerline nerd-font + awesome-config` font with the `Solarized Dark` color theme.
11
12
 
12
- ![Example #1](readme/usage1.png)
13
+ ![image](https://user-images.githubusercontent.com/17109060/32149040-04f3125c-bd25-11e7-8003-66fd29bc18d4.png)
13
14
 
14
15
  *If you're interested in knowing the powerlevel9k configuration to get this prompt, have a look at [this gist](https://gist.github.com/athityakumar/1bd5e9e24cd2a1891565573a893993eb).*
15
16
 
16
17
  # Table of contents
17
18
 
18
19
  - [Usage](#usage)
20
+ - [Flags](#flags)
21
+ - `-1`
22
+ - `-a` (or) `--all`
23
+ - `-A` (or) `--almost-all`
24
+ - `-d` (or) `--dirs`
25
+ - `-f` (or) `--files`
26
+ - `-h` (or) `--help`
27
+ - `-l` (or) `--long`
28
+ - `-r` (or) `--report`
29
+ - `-t` (or) `--tree`
30
+ - `--gs` (or) `--git-status`
31
+ - `--sd` (or) `--sort-dirs` or `--group-directories-first`
32
+ - `--sf` (or) `--sort-files`
33
+ - [Combination of flags](#combination-of-flags)
19
34
  - [Installation](#installation)
20
35
  - [Recommended configurations](#recommended-configurations)
21
36
  - [Custom configurations](#custom-configurations)
@@ -28,34 +43,73 @@ A Ruby script that colorizes the `ls` output with color and icons. Here are the
28
43
 
29
44
  [(Back to top)](#table-of-contents)
30
45
 
31
- - With `-a` : `lc` prints all directories, files and dotfiles in current directory.
46
+ Man pages have been added. Checkout `man colorls`.
32
47
 
33
- ![Usage #1](readme/usage1.png)
48
+ ### Flags
34
49
 
35
- - With paths : `lc path(s) -a` prints all directories, files and dotfiles in given directory / directories.
50
+ - With `-1` : Lists one entry per line
36
51
 
37
- ![Usage #2](readme/usage2.png)
52
+ ![image](https://user-images.githubusercontent.com/17109060/32149062-4f0547ca-bd25-11e7-98b6-587467379704.png)
38
53
 
39
- - With `--report` or `-r` flag : `lc path(s) -r -a` : Prints all directories, files and dotfiles in directories, along with a brief report about number of files and folders shown.
54
+ - With `-a` (or) `--all` : Does not ignore entries starting with '.'
40
55
 
41
- ![Usage #3](readme/usage3.png)
42
- ![Usage #4](readme/usage4.png)
56
+ ![image](https://user-images.githubusercontent.com/17109060/32149045-182eb39e-bd25-11e7-83d4-897cb14bcff3.png)
43
57
 
44
- - With `--sort-dirs` / `-sd` or `--sort-files` / `-sf` : Entries are sorted directories-first or files-first, and then alphabetically (case-insensitively) before being printed.
58
+ - With `-A` (or) `--almost-all` : Does not ignore entries starting with '.', except `./` and `../`
45
59
 
46
- ![Usage #5](readme/usage5.png)
47
- ![Usage #6](readme/usage6.png)
60
+ ![image](https://user-images.githubusercontent.com/17109060/32149046-1ef7664e-bd25-11e7-8bd9-bfc3c8b27b74.png)
48
61
 
49
- - With `--dirs` / `-d` or `--files` / `-f` : Entries are filtered so that only directories or files are shown.
62
+ - With `-d` (or) `--dirs` : Shows only directories
50
63
 
51
- ![Usage #7](readme/usage7.png)
52
- ![Usage #8](readme/usage8.png)
64
+ ![image](https://user-images.githubusercontent.com/17109060/32149066-5f842aa8-bd25-11e7-9bf0-23313b717182.png)
53
65
 
54
- - With `-1` : Entries are printed in a column (one per line), just like `ls -1` does.
66
+ - With `-f` (or) `--files` : Shows only files
55
67
 
56
- ![Usage #9](readme/usage9.png)
68
+ ![image](https://user-images.githubusercontent.com/17109060/32149065-5a27c9d4-bd25-11e7-9a2b-fd731d76a058.png)
57
69
 
58
- - Additional flags: `--almost-all` or `-A`, `--long` or `-l`, `--tree` or `-t`
70
+ - With `-h` (or) `--help` : Prints a very helpful help menu
71
+
72
+ ![image](https://user-images.githubusercontent.com/17109060/32149096-cf2cf5b0-bd25-11e7-84b6-909d79099c98.png)
73
+
74
+ - With `-l` (or) `--long` : Shows in long listing format
75
+
76
+ ![image](https://user-images.githubusercontent.com/17109060/32149049-2a63ae48-bd25-11e7-943c-5ceed25bd693.png)
77
+
78
+ - With `-r` (or) `--report` : Shows brief report about number of files and folders shown
79
+
80
+ ![image](https://user-images.githubusercontent.com/17109060/32149082-96a83fec-bd25-11e7-9081-7f77e4c90e90.png)
81
+
82
+ - With `-t` (or) `--tree` : Shows tree view of the directory
83
+
84
+ ![image](https://user-images.githubusercontent.com/17109060/32149051-32e596e4-bd25-11e7-93a9-5e50c8d2bb19.png)
85
+
86
+ - With `--gs` (or) `--git-status` : Shows git status for each entry
87
+
88
+ ![image](https://user-images.githubusercontent.com/17109060/32149075-7a1a1954-bd25-11e7-964e-1adb173aa2b9.png)
89
+
90
+ - With `--sd` (or) `--sort-dirs` or `--group-directories-first` : Shows directories first, followed by files
91
+
92
+ ![image](https://user-images.githubusercontent.com/17109060/32149068-65117fc0-bd25-11e7-8ada-0b055603e3fd.png)
93
+
94
+ - With `--sf` (or) `--sort-files` : Shows files first, followed by directories
95
+
96
+ ![image](https://user-images.githubusercontent.com/17109060/32149071-6b379de4-bd25-11e7-8764-a0c577e526a1.png)
97
+
98
+ - With color options : `--light` or `--dark` can be passed as a flag, to choose the appropriate color scheme. By default, the dark color scheme is chosen. In order to tweak any color, read [Custom configurations](#custom-configurations).
99
+
100
+ ### Combination of flags
101
+
102
+ - Using `--gs` with `-t` :
103
+
104
+ ![image](https://user-images.githubusercontent.com/17109060/32149076-8423c864-bd25-11e7-816e-8642643d2c27.png)
105
+
106
+ - Using `--gs` with `-l` :
107
+
108
+ ![image](https://user-images.githubusercontent.com/17109060/32149078-899b0622-bd25-11e7-9810-d398eaa77e32.png)
109
+
110
+ - Using `--sd` with `-l` and `-A` :
111
+
112
+ ![image](https://user-images.githubusercontent.com/17109060/32149084-9eb2a416-bd25-11e7-8fb7-a9d336c6e038.png)
59
113
 
60
114
  # Installation
61
115
 
@@ -82,16 +136,17 @@ A Ruby script that colorizes the `ls` output with color and icons. Here are the
82
136
 
83
137
  5. Start using `colorls` :tada:
84
138
 
85
- 6. Have a look at [Recommended configurations](#recommended-configurations).
139
+ 6. Have a look at [Recommended configurations](#recommended-configurations) and [Custom configurations](#custom-configurations).
86
140
 
87
141
  # Recommended configurations
88
142
 
89
143
  [(Back to top)](#table-of-contents)
90
144
 
91
- 1. To add some short command (say, `lc`) with some flag options (say, `-r`)b y default, add this to your shell configuration file (`~/.bashrc`, `~/.zshrc` or `~/.fishrc`) :
145
+ 1. To add some short command (say, `lc`) with some flag options (say, `-l`, `-A`, `--sd`) by default, add this to your shell configuration file (`~/.bashrc`, `~/.zshrc`, etc.) :
92
146
  ```sh
93
- alias lc='colorls -r'
147
+ alias lc='colorls -lA --sd'
94
148
  ```
149
+
95
150
  2. For changing the icon(s) to other unicode icons of choice (select icons from [here](https://nerdfonts.com/)), change the YAML files in a text editor of your choice (say, `subl`)
96
151
 
97
152
  ```sh
@@ -102,17 +157,36 @@ A Ruby script that colorizes the `ls` output with color and icons. Here are the
102
157
 
103
158
  [(Back to top)](#table-of-contents)
104
159
 
105
- You can overwrite the existing icons and colors mapping by creating yaml files in ~/.config/lscolors.
160
+ You can overwrite the existing icons and colors mapping by copying the yaml files from `$(dirname $(gem which colorls))/yaml` into `~/.config/colorls`, and changing them.
106
161
 
107
- Each .yaml file inside the lib/colorls/yaml directory of this repo can be overwrited.
162
+ - To overwrite color mapping :
108
163
 
109
- Let's say you want to add an icon for swift files, you might create a `files.yaml` inside `~/.config/lscolors` and add the following:
164
+ Please have a look at the [list of supported color names](https://github.com/sickill/rainbow#color-list). Let's say that you're using the dark color scheme and would like to change the color of untracked file (`??`) in the `--git-status` flag to yellow. Copy the defaut `dark_colors.yaml` and change it.
165
+
166
+ ```sh
167
+ cp $(dirname $(gem which colorls))/yaml/dark_colors.yaml ~/.config/colorls/dark_colors.yaml`
168
+ ```
169
+
170
+ In the `~/.config/colorls/dark_colors.yaml` file, change the color set for `untracked` from `darkorange` to `yellow`, and save the change.
171
+
172
+ ```
173
+ untracked: yellow
174
+ ```
175
+
176
+ - To overwrite icon mapping :
177
+
178
+ Please have a look at the [list of supported icons](https://nerdfonts.com/). Let's say you want to add an icon for swift files. Copy the default `files.yaml` and change it.
179
+
180
+ ```sh
181
+ cp $(dirname $(gem which colorls))/yaml/files.yaml ~/.config/colorls/files.yaml`
182
+ ```
183
+
184
+ In the `~/.config/colorls/files.yaml` file, add a new icon / change an existing icon, and save the change.
110
185
 
111
- ```
112
- swift: "\uF179"
113
- ```
114
186
 
115
- Which will add the Apple logo to swift files.
187
+ ```
188
+ swift: "\uF179"
189
+ ```
116
190
 
117
191
  # Updating
118
192
 
data/Rakefile CHANGED
@@ -6,6 +6,40 @@ require 'rspec/core/rake_task'
6
6
  RSpec::Core::RakeTask.new
7
7
 
8
8
  require 'rubocop/rake_task'
9
- RuboCop::RakeTask.new
9
+ RuboCop::RakeTask.new do |task|
10
+ task.requires << 'rubocop-rspec'
11
+ end
12
+
13
+ desc 'Build the manual'
14
+ file 'man/colorls.1' => ['man/colorls.1.ronn', 'lib/colorls/flags.rb'] do
15
+ require 'colorls'
16
+ require 'ronn'
17
+
18
+ flags = ColorLS::Flags.new
19
+ attributes = {
20
+ date: Date.iso8601(`git log -1 --pretty=format:%aI -- man/colorls.1`),
21
+ manual: 'colorls Manual',
22
+ organization: "colorls #{ColorLS::VERSION}"
23
+ }
24
+ doc = Ronn::Document.new(nil, attributes) do
25
+ template = IO.read('man/colorls.1.ronn')
26
+
27
+ section = ''
28
+ flags.options.each do |o|
29
+ section += <<OPTION
30
+ * `#{o.flags.join('`, `')}`:
31
+ #{o.desc.join("<br>\n")}
32
+
33
+ OPTION
34
+ end
35
+ template.sub('{{ OPTIONS }}', section)
36
+ end
37
+ IO.write('man/colorls.1', doc.convert('roff'))
38
+ end
39
+
40
+ desc 'Build the Zsh completion file'
41
+ file 'zsh/_colorls' => ['lib/colorls/flags.rb'] do
42
+ ruby "exe/colorls '--*-completion-zsh=colorls' > zsh/_colorls"
43
+ end
10
44
 
11
45
  task default: %w[spec rubocop]
@@ -14,9 +14,16 @@ ColorLS::POST_INSTALL_MESSAGE = %(
14
14
  Help menu : `colorls -h` provides all possible flag options
15
15
 
16
16
  Tab completion enabled for flags
17
+
18
+ -t flag : Previously short for --tree, has been re-allocated to sort results by time
19
+ -r flag : Previously short for --report, has been re-allocated to reverse sort results
20
+
21
+ Man pages have been added. Checkout `man colorls`.
22
+
17
23
  *******************************************************************
18
24
  ).freeze
19
25
 
26
+ # rubocop:disable Metrics/BlockLength
20
27
  Gem::Specification.new do |spec|
21
28
  spec.name = 'colorls'
22
29
  spec.version = ColorLS::VERSION
@@ -29,20 +36,27 @@ Gem::Specification.new do |spec|
29
36
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
30
37
  f.match(%r{^(test|spec|features)/})
31
38
  end
39
+
32
40
  spec.bindir = 'exe'
33
41
  spec.executables = 'colorls'
34
42
  spec.require_paths = ['lib']
35
43
 
36
44
  spec.post_install_message = ColorLS::POST_INSTALL_MESSAGE
37
45
 
46
+ spec.add_runtime_dependency 'clocale'
38
47
  spec.add_runtime_dependency 'filesize'
48
+ spec.add_runtime_dependency 'manpages'
39
49
  spec.add_runtime_dependency 'rainbow'
40
- spec.add_runtime_dependency 'rake'
41
50
 
42
51
  spec.add_development_dependency 'bundler', '~> 1.15'
43
52
  spec.add_development_dependency 'diffy'
53
+ spec.add_development_dependency 'rake'
54
+ spec.add_development_dependency 'ronn'
44
55
  spec.add_development_dependency 'rspec'
45
56
  spec.add_development_dependency 'rspec-its'
46
57
  spec.add_development_dependency 'rubocop'
58
+ spec.add_development_dependency 'rubocop-rspec'
47
59
  spec.add_development_dependency 'rubygems-tasks'
60
+ spec.add_development_dependency 'simplecov'
48
61
  end
62
+ # rubocop:enable Metrics/BlockLength
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'colorls'
4
+
4
5
  ColorLS::Flags.new(*ARGV).process
5
6
  true
@@ -1,10 +1,14 @@
1
1
  require 'yaml'
2
2
  require 'etc'
3
+ require 'English'
3
4
  require 'filesize'
5
+ require 'io/console'
4
6
  require 'rainbow/ext/string'
7
+ require 'clocale'
5
8
 
6
9
  require 'colorls/core'
10
+ require 'colorls/fileinfo'
7
11
  require 'colorls/flags'
8
- require 'colorls/load_from_yaml'
12
+ require 'colorls/yaml'
9
13
  require 'colorls/monkeys'
10
14
  require 'colorls/git'
@@ -1,23 +1,29 @@
1
1
  module ColorLS
2
2
  class Core
3
- def initialize(input=nil, all: false, report: false, sort: false, show: false,
4
- one_per_line: false, git_status: false,long: false, almost_all: false, tree: false, colors: [])
5
- @input = init_input_path(input)
3
+ def initialize(input, all: false, report: false, sort: false, show: false,
4
+ mode: nil, git_status: false, almost_all: false, colors: [], group: nil,
5
+ reverse: false)
6
+ @input = File.absolute_path(input)
6
7
  @count = {folders: 0, recognized_files: 0, unrecognized_files: 0}
7
8
  @all = all
8
9
  @almost_all = almost_all
9
10
  @report = report
10
11
  @sort = sort
12
+ @reverse = reverse
13
+ @group = group
11
14
  @show = show
12
- @one_per_line = one_per_line
13
- @long = long
14
- @tree = tree
15
+ @one_per_line = mode == :one_per_line
16
+ @long = mode == :long
17
+ @tree = mode == :tree
15
18
  process_git_status_details(git_status)
16
- @screen_width = `tput cols`.chomp.to_i
19
+
20
+ @screen_width = IO.console.winsize[1]
21
+ @screen_width = 80 if @screen_width.zero?
22
+
17
23
  @colors = colors
18
24
 
19
- @contents = init_contents(@input)
20
- @max_widths = @contents.map(&:length)
25
+ @contents = init_contents(input)
26
+ @max_widths = @contents.map { |c| c.name.length }
21
27
  init_icons
22
28
  end
23
29
 
@@ -29,45 +35,35 @@ module ColorLS
29
35
  tree_traverse(@input, 0, 2)
30
36
  else
31
37
  @contents = chunkify
32
- @max_widths = @contents.transpose.map { |c| c.map(&:length).max }
33
38
  @contents.each { |chunk| ls_line(chunk) }
34
39
  end
35
- print "\n"
36
40
  display_report if @report
37
41
  true
38
42
  end
39
43
 
40
44
  private
41
45
 
42
- def init_input_path(input)
43
- return Dir.pwd unless input
44
- return input unless Dir.exist?(input)
46
+ def init_contents(path)
47
+ info = FileInfo.new(path, link_info = @long)
45
48
 
46
- actual = Dir.pwd
47
- Dir.chdir(input)
48
- input = Dir.pwd
49
- Dir.chdir(actual)
50
- input
51
- end
49
+ if info.directory?
50
+ @contents = Dir.entries(path)
52
51
 
53
- def init_contents(path)
54
- is_directory = Dir.exist?(path)
55
- @contents = if is_directory
56
- Dir.entries(path)
57
- else
58
- @input = File.dirname(path)
59
- [File.basename(path)]
60
- end
52
+ filter_hidden_contents
61
53
 
62
- filter_hidden_contents if is_directory
63
- filter_contents(path) if @show
64
- sort_contents(path) if @sort
54
+ @contents.map! { |e| FileInfo.new(File.join(path, e), link_info = @long) }
65
55
 
56
+ filter_contents if @show
57
+ sort_contents if @sort
58
+ group_contents if @group
59
+ else
60
+ @contents = [info]
61
+ end
66
62
  @total_content_length = @contents.length
67
63
 
68
64
  return @contents unless @long
69
- init_user_lengths(path)
70
- init_group_lengths(path)
65
+ init_user_lengths
66
+ init_group_lengths
71
67
  @contents
72
68
  end
73
69
 
@@ -76,61 +72,52 @@ module ColorLS
76
72
  @contents.keep_if { |x| !x.start_with? '.' } unless @all || @almost_all
77
73
  end
78
74
 
79
- def init_user_lengths(path)
75
+ def init_user_lengths
80
76
  @userlength = @contents.map do |c|
81
- next 0 unless File.exist?("#{path}/#{c}")
82
- begin
83
- user = Etc.getpwuid(File.stat("#{path}/#{c}").uid).name
84
- rescue ArgumentError
85
- user = File.stat("#{path}/#{c}").uid
86
- end
87
- user.to_s.length
77
+ c.owner.length
88
78
  end.max
89
79
  end
90
80
 
91
- def init_group_lengths(path)
81
+ def init_group_lengths
92
82
  @grouplength = @contents.map do |c|
93
- next 0 unless File.exist?("#{path}/#{c}")
94
- begin
95
- group = Etc.getgrgid(File.stat("#{path}/#{c}").gid).name
96
- rescue ArgumentError
97
- group = File.stat("#{path}/#{c}").gid
98
- end
99
- group.to_s.length
83
+ c.group.length
100
84
  end.max
101
85
  end
102
86
 
103
- def filter_contents(path)
87
+ def filter_contents
104
88
  @contents.keep_if do |x|
105
- next Dir.exist?("#{path}/#{x}") if @show == :dirs
106
- !Dir.exist?("#{path}/#{x}")
89
+ x.directory? == (@show == :dirs)
107
90
  end
108
91
  end
109
92
 
110
- def sort_contents(path)
111
- @contents.sort! { |a, b| cmp_by_dirs(path, a, b) }
93
+ def sort_contents
94
+ case @sort
95
+ when :time
96
+ @contents.sort_by! { |a| -a.mtime.to_f }
97
+ when :size
98
+ @contents.sort_by! { |a| -a.size }
99
+ else
100
+ @contents.sort_by! { |a| CLocale.strxfrm(a.name) }
101
+ end
102
+ @contents.reverse! if @reverse
112
103
  end
113
104
 
114
- def cmp_by_dirs(path, a, b)
115
- is_a_dir = Dir.exist?("#{path}/#{a}")
116
- is_b_dir = Dir.exist?("#{path}/#{b}")
117
-
118
- return cmp_by_alpha(a, b) unless is_a_dir ^ is_b_dir
105
+ def group_contents
106
+ return unless @group
119
107
 
120
- result = is_a_dir ? -1 : 1
121
- result *= -1 if @sort == :files
122
- result
123
- end
108
+ dirs, files = @contents.partition(&:directory?)
124
109
 
125
- def cmp_by_alpha(a, b)
126
- a.downcase <=> b.downcase
110
+ @contents = case @group
111
+ when :dirs then dirs.push(*files)
112
+ when :files then files.push(*dirs)
113
+ end
127
114
  end
128
115
 
129
116
  def init_icons
130
- @files = ColorLS.load_from_yaml('files.yaml')
131
- @file_aliases = ColorLS.load_from_yaml('file_aliases.yaml', true)
132
- @folders = ColorLS.load_from_yaml('folders.yaml')
133
- @folder_aliases = ColorLS.load_from_yaml('folder_aliases.yaml', true)
117
+ @files = ColorLS::Yaml.new('files.yaml').load
118
+ @file_aliases = ColorLS::Yaml.new('file_aliases.yaml').load(aliase: true)
119
+ @folders = ColorLS::Yaml.new('folders.yaml').load
120
+ @folder_aliases = ColorLS::Yaml.new('folder_aliases.yaml').load(aliase: true)
134
121
 
135
122
  @file_keys = @files.keys
136
123
  @file_aliase_keys = @file_aliases.keys
@@ -144,25 +131,25 @@ module ColorLS
144
131
  def chunkify
145
132
  return @contents.zip if @one_per_line || @long
146
133
 
147
- chunk_size = @contents.count
134
+ chunk_size = @contents.size
135
+ max_widths = @max_widths
148
136
 
149
- until in_line(chunk_size) || chunk_size <= 1
137
+ until in_line(chunk_size, max_widths) || chunk_size <= 1
150
138
  chunk_size -= 1
151
- chunk = get_chunk(chunk_size)
139
+ max_widths = @max_widths.each_slice(chunk_size).to_a
140
+ max_widths[-1] += [0] * (chunk_size - max_widths.last.size)
141
+ max_widths = max_widths.transpose.map(&:max)
152
142
  end
153
-
154
- chunk || [@contents]
143
+ @max_widths = max_widths
144
+ @contents = get_chunk(chunk_size)
155
145
  end
156
146
 
157
147
  def get_chunk(chunk_size)
158
- chunk = @contents.each_slice(chunk_size).to_a
159
- chunk[-1] += [''] * (chunk_size - chunk.last.count)
160
- @max_widths = chunk.transpose.map { |c| c.map(&:length).max }
161
- chunk
148
+ @contents.each_slice(chunk_size).to_a
162
149
  end
163
150
 
164
- def in_line(chunk_size)
165
- (@max_widths.sum + 12 * chunk_size <= @screen_width)
151
+ def in_line(chunk_size, max_widths)
152
+ (max_widths.sum + 12 * chunk_size <= @screen_width)
166
153
  end
167
154
 
168
155
  def display_report
@@ -193,54 +180,39 @@ module ColorLS
193
180
  mode
194
181
  end
195
182
 
196
- def user_info(stat)
197
- begin
198
- user = Etc.getpwuid(stat.uid).name
199
- rescue ArgumentError
200
- user = stat.uid
201
- end
202
- user = user.to_s.ljust(@userlength, ' ')
203
- user.colorize(@colors[:user]) if user == Etc.getlogin
183
+ def user_info(content)
184
+ user = content.owner.ljust(@userlength, ' ')
185
+ user.colorize(@colors[:user]) if content.owned?
204
186
  end
205
187
 
206
- def group_info(stat)
207
- begin
208
- group = Etc.getgrgid(stat.gid).name
209
- rescue ArgumentError
210
- group = stat.gid
211
- end
188
+ def group_info(group)
212
189
  group.to_s.ljust(@grouplength, ' ').colorize(@colors[:normal])
213
190
  end
214
191
 
215
- def size_info(stat)
216
- size = Filesize.from("#{stat.size} B").pretty.split(' ')
192
+ def size_info(filesize)
193
+ size = Filesize.from("#{filesize} B").pretty.split(' ')
217
194
  size = "#{size[0][0..-4].rjust(3,' ')} #{size[1].ljust(3,' ')}"
218
- return size.colorize(@colors[:file_large]) if stat.size >= 512 * 1024 ** 2
219
- return size.colorize(@colors[:file_medium]) if stat.size >= 128 * 1024 ** 2
195
+ return size.colorize(@colors[:file_large]) if filesize >= 512 * 1024 ** 2
196
+ return size.colorize(@colors[:file_medium]) if filesize >= 128 * 1024 ** 2
220
197
  size.colorize(@colors[:file_small])
221
198
  end
222
199
 
223
- def mtime_info(stat)
224
- mtime = stat.mtime.asctime
225
- return mtime.colorize(@colors[:hour_old]) if Time.now - stat.mtime < 60 * 60
226
- return mtime.colorize(@colors[:day_old]) if Time.now - stat.mtime < 24 * 60 * 60
200
+ def mtime_info(file_mtime)
201
+ mtime = file_mtime.asctime
202
+ now = Time.now
203
+ return mtime.colorize(@colors[:hour_old]) if now - file_mtime < 60 * 60
204
+ return mtime.colorize(@colors[:day_old]) if now - file_mtime < 24 * 60 * 60
227
205
  mtime.colorize(@colors[:no_modifier])
228
206
  end
229
207
 
230
208
  def process_git_status_details(git_status)
231
209
  return false unless git_status
232
210
 
233
- actual_path = Dir.pwd
234
- Dir.chdir(@input)
235
- until File.exist?('.git') # check whether the repository is git controlled
236
- return false if Dir.pwd=='/'
237
- Dir.chdir('..')
238
- end
211
+ @git_root_path = IO.popen(['git', '-C', @input, 'rev-parse', '--show-toplevel'], err: :close, &:gets)
239
212
 
240
- @git_root_path = Dir.pwd
241
- Dir.chdir(actual_path)
213
+ return false unless $CHILD_STATUS.success?
242
214
 
243
- @git_status = Git.status(@git_root_path)
215
+ @git_status = Git.status(@git_root_path.chomp!)
244
216
  end
245
217
 
246
218
  def git_info(path, content)
@@ -248,14 +220,14 @@ module ColorLS
248
220
 
249
221
  # puts "\n\n"
250
222
 
251
- Dir.chdir(@git_root_path)
252
223
  relative_path = path.remove(@git_root_path+'/')
253
224
  relative_path = relative_path==path ? '' : relative_path+'/'
254
225
  content_path = "#{relative_path}#{content}"
255
- content_type = Dir.exist?("#{@git_root_path}/#{content_path}") ? :dir : :file
256
226
 
257
- if content_type == :file then git_file_info(content_path)
258
- else git_dir_info(content_path)
227
+ if content.directory?
228
+ git_dir_info(content_path)
229
+ else
230
+ git_file_info(content_path)
259
231
  end
260
232
  # puts "\n\n"
261
233
  end
@@ -265,34 +237,46 @@ module ColorLS
265
237
  Git.colored_status_symbols(@git_status[path], @colors)
266
238
  end
267
239
 
240
+ Dir.class_eval do
241
+ def self.deep_entries(path)
242
+ (Dir.entries(path) - ['.', '..']).map do |entry|
243
+ if Dir.exist?("#{path}/#{entry}")
244
+ Dir.deep_entries("#{path}/#{entry}")
245
+ else
246
+ entry
247
+ end
248
+ end.flatten
249
+ end
250
+ end
251
+
268
252
  def git_dir_info(path)
269
- modes = @git_status.select { |file, _mode| file.start_with?(path) }.values
253
+ ignored = @git_status.select { |file, mode| file.start_with?(path) && mode=='!!' }.keys
254
+ present = Dir.deep_entries(path).map { |p| "#{path}/#{p}" }
255
+ return ' ' if (present-ignored).empty?
270
256
 
257
+ modes = (present-ignored).map { |file| @git_status[file] }-[nil]
271
258
  return ' ✓ '.colorize(@colors[:unchanged]) if modes.empty?
272
259
  Git.colored_status_symbols(modes.join.uniq, @colors)
273
260
  end
274
261
 
275
- def long_info(path, content)
262
+ def long_info(content)
276
263
  return '' unless @long
277
- unless File.exist?("#{path}/#{content}")
278
- return '[No Info]'.colorize(@colors[:error]) + ' ' * (38 + @userlength + @grouplength)
279
- end
280
- stat = File.stat("#{path}/#{content}")
281
- [mode_info(stat), user_info(stat), group_info(stat), size_info(stat), mtime_info(stat)]
282
- .join(' ')
264
+ [mode_info(content.stats), user_info(content), group_info(content.group),
265
+ size_info(content.size), mtime_info(content.mtime)].join(' ')
283
266
  end
284
267
 
285
- def symlink_info(path, content)
286
- return '' unless @long && File.symlink?("#{path}/#{content}")
287
- if File.exist?("#{path}/#{content}")
288
- " ⇒ #{File.readlink("#{path}/#{content}")}/".colorize(@colors[:link])
268
+ def symlink_info(content)
269
+ return '' unless @long && content.symlink?
270
+ link_info = "#{content.link_target}"
271
+ if content.dead?
272
+ "#{link_info} [Dead link]".colorize(@colors[:dead_link])
289
273
  else
290
- ' ⇒ [Dead link]'.colorize(@colors[:dead_link])
274
+ link_info.colorize(@colors[:link])
291
275
  end
292
276
  end
293
277
 
294
- def slash?(path, content)
295
- Dir.exist?("#{path}/#{content}") ? '/'.colorize(@colors[:dir]) : ' '
278
+ def slash?(content)
279
+ content.directory? ? '/'.colorize(@colors[:dir]) : ' '
296
280
  end
297
281
 
298
282
  def fetch_string(path, content, key, color, increment)
@@ -301,26 +285,26 @@ module ColorLS
301
285
  logo = value.gsub(/\\u[\da-f]{4}/i) { |m| [m[-4..-1].to_i(16)].pack('U') }
302
286
 
303
287
  [
304
- long_info(path, content),
288
+ long_info(content),
305
289
  " #{git_info(path,content)} ",
306
290
  logo.colorize(color),
307
- " #{content.colorize(color)}#{slash?(path, content)}#{symlink_info(path, content)}"
291
+ " #{content.name.colorize(color)}#{slash?(content)}#{symlink_info(content)}"
308
292
  ].join
309
293
  end
310
294
 
311
295
  def ls_line(chunk)
312
- print "\n"
313
296
  chunk.each_with_index do |content, i|
314
- break if content.empty?
297
+ break if content.name.empty?
315
298
 
316
- print " #{fetch_string(@input, content, *options(@input, content))}"
317
- print ' ' * (@max_widths[i] - content.length) unless @one_per_line || @long
299
+ print " #{fetch_string(@input, content, *options(content))}"
300
+ print ' ' * (@max_widths[i] - content.name.length) unless @one_per_line || @long
318
301
  end
302
+ print "\n"
319
303
  end
320
304
 
321
- def options(path, content)
322
- if Dir.exist?("#{path}/#{content}")
323
- key = content.to_sym
305
+ def options(content)
306
+ if content.directory?
307
+ key = content.name.to_sym
324
308
  color = @colors[:dir]
325
309
  return [:folder, color, :folders] unless @all_folders.include?(key)
326
310
  key = @folder_aliases[key] unless @folder_keys.include?(key)
@@ -330,7 +314,7 @@ module ColorLS
330
314
  color = @colors[:recognized_file]
331
315
  return [content.downcase.to_sym, color, :recognized_files] if @file_keys.include?(key)
332
316
 
333
- key = content.split('.').last.downcase.to_sym
317
+ key = content.name.split('.').last.downcase.to_sym
334
318
  return [:file, @colors[:unrecognized_file], :unrecognized_files] unless @all_files.include?(key)
335
319
 
336
320
  key = @file_aliases[key] unless @file_keys.include?(key)
@@ -340,10 +324,10 @@ module ColorLS
340
324
  def tree_traverse(path, prespace, indent)
341
325
  contents = init_contents(path)
342
326
  contents.each do |content|
343
- icon = content == contents.last || Dir.exist?("#{path}/#{content}") ? ' └──' : ' ├──'
327
+ icon = content == contents.last || content.directory? ? ' └──' : ' ├──'
344
328
  print tree_branch_preprint(prespace, indent, icon).colorize(@colors[:tree])
345
- print " #{fetch_string(path, content, *options(path, content))} \n"
346
- next unless Dir.exist? "#{path}/#{content}"
329
+ print " #{fetch_string(path, content, *options(content))} \n"
330
+ next unless content.directory?
347
331
  tree_traverse("#{path}/#{content}", prespace + indent, indent)
348
332
  end
349
333
  end