colorls 1.0.9 → 1.1.0

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 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