From f9df865190a9f666ce05152a3f32e244a5a81332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 08:23:45 +0200 Subject: [PATCH 01/12] Added --sort (case-insensitive) option --- colorls.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/colorls.rb b/colorls.rb index 76dbe69..d5687db 100644 --- a/colorls.rb +++ b/colorls.rb @@ -5,13 +5,19 @@ require 'terminfo' # Source for icons unicode: http://nerdfonts.com/ class ColorLS - def initialize(input, report) + def initialize(input, report, sort) @input = input || Dir.pwd @contents = Dir.entries(@input) - ['.', '..'] @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report + @sort = sort @screen_width = TermInfo.screen_size.last - @max_widths = @contents.map(&:length) + + @contents.sort! { + |a, b| a.downcase <=> b.downcase + } if @sort + + @max_widths = @contents.map(&:length) init_icons end @@ -133,12 +139,19 @@ else report = false end +if args.include?('--sort') + sort = true + args -= %w[--sort] +else + sort = false +end + args.keep_if { |arg| !arg.start_with?('-') } if args.empty? - ColorLS.new(nil, report).ls + ColorLS.new(nil, report, sort).ls else - args.each { |path| ColorLS.new(path, report).ls } + args.each { |path| ColorLS.new(path, report, sort).ls } end true From d3f52a6895ccaeb305f50d9c01fd83653e4e2ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 08:24:41 +0200 Subject: [PATCH 02/12] Made the script executable & added shebang --- colorls.rb | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 colorls.rb diff --git a/colorls.rb b/colorls.rb old mode 100644 new mode 100755 index d5687db..f257246 --- a/colorls.rb +++ b/colorls.rb @@ -1,3 +1,5 @@ +#!/usr/bin/env ruby + require 'colorize' require 'yaml' require 'facets' From d3495cf6f1b4cfad726eecabe4c3bdd31f032b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 08:41:11 +0200 Subject: [PATCH 03/12] Added dirs-first sorting --- colorls.rb | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/colorls.rb b/colorls.rb index f257246..7b60b3c 100755 --- a/colorls.rb +++ b/colorls.rb @@ -12,12 +12,22 @@ class ColorLS @contents = Dir.entries(@input) - ['.', '..'] @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report - @sort = sort @screen_width = TermInfo.screen_size.last - @contents.sort! { - |a, b| a.downcase <=> b.downcase - } if @sort + @contents.sort! { |a, b| + if sort == 'dirs-first' + case + when Dir.exist?("#{@input}/#{a}") && ! Dir.exist?("#{@input}/#{b}") + -1 + when ! Dir.exist?("#{@input}/#{a}") && Dir.exist?("#{@input}/#{b}") + 1 + else + a.downcase <=> b.downcase + end + else + a.downcase <=> b.downcase + end + } if sort @max_widths = @contents.map(&:length) @@ -132,21 +142,19 @@ class ColorLS end end -args = *ARGV +args = *ARGV +report = false +sort = false -if args.include?('--report') || args.include?('-r') - report = true - args -= %w[--report -r] -else - report = false -end +args.each { |arg| + if arg == '--report' || arg == '-r' + report = true + end -if args.include?('--sort') - sort = true - args -= %w[--sort] -else - sort = false -end + if match = arg.match(/^--sort=?(.*)?$/) + sort = match.captures && match.captures[0] == 'dirs-first' ? 'dirs-first' : true + end +} args.keep_if { |arg| !arg.start_with?('-') } From 1e07facec9041f54a9a9a5b17f4b8349fb42541c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 09:00:16 +0200 Subject: [PATCH 04/12] Added -1 option --- colorls.rb | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/colorls.rb b/colorls.rb index 7b60b3c..dc03a86 100755 --- a/colorls.rb +++ b/colorls.rb @@ -7,12 +7,13 @@ require 'terminfo' # Source for icons unicode: http://nerdfonts.com/ class ColorLS - def initialize(input, report, sort) + def initialize(input, report, sort, one_per_line) @input = input || Dir.pwd @contents = Dir.entries(@input) - ['.', '..'] @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report @screen_width = TermInfo.screen_size.last + @one_per_line = one_per_line @contents.sort! { |a, b| if sort == 'dirs-first' @@ -61,14 +62,20 @@ class ColorLS end def chunkify - chunk_size = @contents.count + if @one_per_line + chunks = @contents.map { |x| [x] } + @max_widths = chunks.transpose.map { |c| c.map(&:length).max } + chunks + else + chunk_size = @contents.count - until in_line(chunk_size) || chunk_size <= 1 - chunk_size -= 1 - chunk = get_chunk(chunk_size) + until in_line(chunk_size) || chunk_size <= 1 + chunk_size -= 1 + chunk = get_chunk(chunk_size) + end + + chunk || [@contents] end - - chunk || [@contents] end def get_chunk(chunk_size) @@ -142,15 +149,20 @@ class ColorLS end end -args = *ARGV -report = false -sort = false +args = *ARGV +report = false +sort = false +one_per_line = false args.each { |arg| if arg == '--report' || arg == '-r' report = true end + if arg == '-1' + one_per_line = true + end + if match = arg.match(/^--sort=?(.*)?$/) sort = match.captures && match.captures[0] == 'dirs-first' ? 'dirs-first' : true end @@ -159,9 +171,9 @@ args.each { |arg| args.keep_if { |arg| !arg.start_with?('-') } if args.empty? - ColorLS.new(nil, report, sort).ls + ColorLS.new(nil, report, sort, one_per_line).ls else - args.each { |path| ColorLS.new(path, report, sort).ls } + args.each { |path| ColorLS.new(path, report, sort, one_per_line).ls } end true From 160734fb2c3ea4f4fe849f2767d54d44496f3588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 09:05:58 +0200 Subject: [PATCH 05/12] Updated Readme --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 01b6e23..7315c75 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Color LS +# Color LS [![Build Status](https://travis-ci.org/athityakumar/colorls.svg?branch=master)](https://travis-ci.org/athityakumar/colorls) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) @@ -23,6 +23,10 @@ terminal (Mac OS), `oh-my-zsh` with `powerlevel9k` theme and `powerline nerd-fon ![Usage #3](readme/usage3.png) ![Usage #4](readme/usage4.png) +- With `--sort` or `--sort=dirs-first` : Entries are sorted alphabetically (case-insensitively) before being printed. In case of `--sort=dirs-first` directories are sorted before other files. + +- With `-1` : Entries are printed in a column (one per line), just like `ls -1` does. + # Installation steps 1. Install Ruby (prefably, version > 2.1) @@ -36,8 +40,8 @@ cd ~/bin && git clone https://github.com/athityakumar/colorls.git ``` gem install bundler bundle install - ``` -6. For CLI functionality, add a function (say, `lc`) to your shell configuration file (`~/.bashrc` or `~/.zshrc`) : + ``` +6. For CLI functionality, add a function (say, `lc`) to your shell configuration file (`~/.bashrc` or `~/.zshrc`) : ```sh lc () { ruby ~/bin/colorls/colorls.rb $1; } ``` @@ -56,7 +60,7 @@ _NOTE: If you're iTerm2 on Mac, you may have to enable the nerd-font at iTerm2 > There are a couple of formats that aren't recognized yet. Custom file formats and icons can be added by changing the YAML files in this repository. Also, feel free to send a Pull Request here with the added icons. :smile: -Please feel free to contribute to this project, by +Please feel free to contribute to this project, by - opening an issue for reporting any bug / suggesting any enhancement - cleaning up the `colorls.rb` ruby script with more functionalities. - adding support for more icons by editing the YAML files. From dd4bdc85f35521069e6ed389280f8ba46eb257f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 09:31:16 +0200 Subject: [PATCH 06/12] Added support for passing files as input --- colorls.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/colorls.rb b/colorls.rb index dc03a86..4f31c7d 100755 --- a/colorls.rb +++ b/colorls.rb @@ -8,8 +8,18 @@ require 'terminfo' # Source for icons unicode: http://nerdfonts.com/ class ColorLS def initialize(input, report, sort, one_per_line) - @input = input || Dir.pwd - @contents = Dir.entries(@input) - ['.', '..'] + @input = input || Dir.pwd + + if Dir.exists?(@input) + @contents = Dir.entries(@input) - ['.', '..'] + else + if File.exists?(@input) + @contents = [@input] + else + raise ArgumentError, "Specified path doesn't exist: " + @input + end + end + @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report @screen_width = TermInfo.screen_size.last From 056657b97e6997f19673eef4e1fc53f55840aea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Tue, 4 Jul 2017 10:40:34 +0200 Subject: [PATCH 07/12] Corrected rubocop issues --- colorls.rb | 94 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/colorls.rb b/colorls.rb index 4f31c7d..79bd914 100755 --- a/colorls.rb +++ b/colorls.rb @@ -6,47 +6,63 @@ require 'facets' require 'terminfo' # Source for icons unicode: http://nerdfonts.com/ -class ColorLS +class ColorLS # rubocop:disable ClassLength def initialize(input, report, sort, one_per_line) - @input = input || Dir.pwd - - if Dir.exists?(@input) - @contents = Dir.entries(@input) - ['.', '..'] - else - if File.exists?(@input) - @contents = [@input] - else - raise ArgumentError, "Specified path doesn't exist: " + @input - end - end - + @input = input || Dir.pwd @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report - @screen_width = TermInfo.screen_size.last + @sort = sort @one_per_line = one_per_line + @screen_width = TermInfo.screen_size.last - @contents.sort! { |a, b| - if sort == 'dirs-first' - case - when Dir.exist?("#{@input}/#{a}") && ! Dir.exist?("#{@input}/#{b}") - -1 - when ! Dir.exist?("#{@input}/#{a}") && Dir.exist?("#{@input}/#{b}") - 1 - else - a.downcase <=> b.downcase - end - else - a.downcase <=> b.downcase - end - } if sort + init_contents @max_widths = @contents.map(&:length) init_icons end + def init_contents + if Dir.exist?(@input) + @contents = Dir.entries(@input) - ['.', '..'] + elsif File.exist?(@input) + @contents = [@input] + else + raise ArgumentError, "Specified path doesn't exist: " + @input + end + + sort_contents + end + + def sort_contents + return unless @sort + + @contents.sort! do |a, b| + if @sort == 'dirs-first' + cmp_by_dirs(a, b) + else + cmp_by_alpha(a, b) + end + end + end + + def cmp_by_dirs(a, b) + if Dir.exist?("#{@input}/#{a}") && !Dir.exist?("#{@input}/#{b}") + -1 + elsif !Dir.exist?("#{@input}/#{a}") && Dir.exist?("#{@input}/#{b}") + 1 + else + cmp_by_alpha(a, b) + end + end + + def cmp_by_alpha(a, b) + a.downcase <=> b.downcase + end + def ls @contents = chunkify + @max_widths = @contents.transpose.map { |c| c.map(&:length).max } @contents.each { |chunk| ls_line(chunk) } print "\n" display_report if @report @@ -73,9 +89,7 @@ class ColorLS def chunkify if @one_per_line - chunks = @contents.map { |x| [x] } - @max_widths = chunks.transpose.map { |c| c.map(&:length).max } - chunks + @contents.map { |x| [x] } else chunk_size = @contents.count @@ -91,7 +105,6 @@ class ColorLS def get_chunk(chunk_size) chunk = @contents.each_slice(chunk_size).to_a chunk.last += [''] * (chunk_size - chunk.last.count) - @max_widths = chunk.transpose.map { |c| c.map(&:length).max } chunk end @@ -164,19 +177,16 @@ report = false sort = false one_per_line = false -args.each { |arg| - if arg == '--report' || arg == '-r' - report = true - end +args.each do |arg| + report = true if ['--report', '-r'].include?(arg) + one_per_line = true if arg == '-1' - if arg == '-1' - one_per_line = true - end + match = arg.match(/^--sort=?(.*)?$/) - if match = arg.match(/^--sort=?(.*)?$/) - sort = match.captures && match.captures[0] == 'dirs-first' ? 'dirs-first' : true + if match + sort = match.captures[0] == 'dirs-first' ? 'dirs-first' : true end -} +end args.keep_if { |arg| !arg.start_with?('-') } From 487e3788a1ebbb6e1ff0dae9ed62b72363f5a228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Wed, 5 Jul 2017 07:27:39 +0200 Subject: [PATCH 08/12] After-review corrections Changed args to the contructor to named parameters. Changed CLI arguments' names. --- colorls.rb | 83 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/colorls.rb b/colorls.rb index 79bd914..044078e 100755 --- a/colorls.rb +++ b/colorls.rb @@ -7,11 +7,12 @@ require 'terminfo' # Source for icons unicode: http://nerdfonts.com/ class ColorLS # rubocop:disable ClassLength - def initialize(input, report, sort, one_per_line) + def initialize(input, report:, sort:, show:, one_per_line:) @input = input || Dir.pwd @count = { folders: 0, recognized_files: 0, unrecognized_files: 0 } @report = report @sort = sort + @show = show @one_per_line = one_per_line @screen_width = TermInfo.screen_size.last @@ -31,26 +32,38 @@ class ColorLS # rubocop:disable ClassLength raise ArgumentError, "Specified path doesn't exist: " + @input end + filter_contents sort_contents end + def filter_contents + return unless @show + + @contents.keep_if do |x| + if @show == 'dirs' + Dir.exist?("#{@input}/#{x}") + else + !Dir.exist?("#{@input}/#{x}") + end + end + end + def sort_contents return unless @sort @contents.sort! do |a, b| - if @sort == 'dirs-first' - cmp_by_dirs(a, b) - else - cmp_by_alpha(a, b) - end + cmp_by_dirs(a, b) end end def cmp_by_dirs(a, b) - if Dir.exist?("#{@input}/#{a}") && !Dir.exist?("#{@input}/#{b}") - -1 - elsif !Dir.exist?("#{@input}/#{a}") && Dir.exist?("#{@input}/#{b}") - 1 + is_a_dir = Dir.exist?("#{@input}/#{a}") + is_b_dir = Dir.exist?("#{@input}/#{b}") + + if is_a_dir ^ is_b_dir + result = is_a_dir ? -1 : 1 + result *= -1 if @sort == 'files' + result else cmp_by_alpha(a, b) end @@ -89,7 +102,7 @@ class ColorLS # rubocop:disable ClassLength def chunkify if @one_per_line - @contents.map { |x| [x] } + @contents.zip else chunk_size = @contents.count @@ -172,28 +185,46 @@ class ColorLS # rubocop:disable ClassLength end end -args = *ARGV -report = false -sort = false -one_per_line = false +args = *ARGV +report = args.include?('--report') || args.include?('-r') +one_per_line = args.include?('-1') +sort_files_first = args.include?('-sf') || args.include?('--sort-files') +sort_dirs_first = args.include?('-sd') || args.include?('--sort-dirs') +show_files_only = args.include?('-f') || args.include?('--files') +show_dirs_only = args.include?('-d') || args.include?('--dirs') -args.each do |arg| - report = true if ['--report', '-r'].include?(arg) - one_per_line = true if arg == '-1' +sort = if sort_files_first + 'files' + elsif sort_dirs_first + 'dirs' + else + false + end - match = arg.match(/^--sort=?(.*)?$/) - - if match - sort = match.captures[0] == 'dirs-first' ? 'dirs-first' : true - end -end +show = if show_files_only + 'files' + elsif show_dirs_only + 'dirs' + else + false + end args.keep_if { |arg| !arg.start_with?('-') } if args.empty? - ColorLS.new(nil, report, sort, one_per_line).ls + ColorLS.new(nil, + report: report, + sort: sort, + show: show, + one_per_line: one_per_line).ls else - args.each { |path| ColorLS.new(path, report, sort, one_per_line).ls } + args.each do |path| + ColorLS.new(path, + report: report, + sort: sort, + show: show, + one_per_line: one_per_line).ls + end end true From a7ec665da46ac343a75bded292770078a077f374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Wed, 5 Jul 2017 07:36:05 +0200 Subject: [PATCH 09/12] Updated the README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7315c75..f10f5d9 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,9 @@ terminal (Mac OS), `oh-my-zsh` with `powerlevel9k` theme and `powerline nerd-fon ![Usage #3](readme/usage3.png) ![Usage #4](readme/usage4.png) -- With `--sort` or `--sort=dirs-first` : Entries are sorted alphabetically (case-insensitively) before being printed. In case of `--sort=dirs-first` directories are sorted before other files. +- With `--sort-dirs` / `-sd` or `--sort-files` / `-sf` : Entries are sorted directories-first or files-first, and then alphabetically (case-insensitively) before being printed. + +-With `--dirs` / `-d` or `--files` / `-f` : Entries are filtered so that only directories or files are shown. - With `-1` : Entries are printed in a column (one per line), just like `ls -1` does. From eca28f9516ac1f418b47d13470d48bdef1555714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Wed, 5 Jul 2017 08:29:22 +0200 Subject: [PATCH 10/12] Removed support for files as input --- colorls.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/colorls.rb b/colorls.rb index 044078e..ba02cc2 100755 --- a/colorls.rb +++ b/colorls.rb @@ -24,14 +24,12 @@ class ColorLS # rubocop:disable ClassLength end def init_contents - if Dir.exist?(@input) - @contents = Dir.entries(@input) - ['.', '..'] - elsif File.exist?(@input) - @contents = [@input] - else - raise ArgumentError, "Specified path doesn't exist: " + @input + unless Dir.exist?(@input) + raise ArgumentError, "Specified directory doesn't exist: " + @input end + @contents = Dir.entries(@input) - ['.', '..'] + filter_contents sort_contents end From f2d78eafe9928f36c8194f8c842b3c65b4331e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Wed, 5 Jul 2017 08:59:20 +0200 Subject: [PATCH 11/12] Corrected chunkifying --- colorls.rb | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/colorls.rb b/colorls.rb index ba02cc2..499c75c 100755 --- a/colorls.rb +++ b/colorls.rb @@ -73,7 +73,6 @@ class ColorLS # rubocop:disable ClassLength def ls @contents = chunkify - @max_widths = @contents.transpose.map { |c| c.map(&:length).max } @contents.each { |chunk| ls_line(chunk) } print "\n" display_report if @report @@ -100,22 +99,24 @@ class ColorLS # rubocop:disable ClassLength def chunkify if @one_per_line - @contents.zip - else - chunk_size = @contents.count - - until in_line(chunk_size) || chunk_size <= 1 - chunk_size -= 1 - chunk = get_chunk(chunk_size) - end - - chunk || [@contents] + @max_widths = [@max_widths.max] + return @contents.zip end + + chunk_size = @contents.count + + until in_line(chunk_size) || chunk_size <= 1 + chunk_size -= 1 + chunk = get_chunk(chunk_size) + end + + chunk || [@contents] end def get_chunk(chunk_size) - chunk = @contents.each_slice(chunk_size).to_a - chunk.last += [''] * (chunk_size - chunk.last.count) + chunk = @contents.each_slice(chunk_size).to_a + chunk.last += [''] * (chunk_size - chunk.last.count) + @max_widths = chunk.transpose.map { |c| c.map(&:length).max } chunk end From ed3a5cfc7cd0f35e13bb1a7a4087c040db913c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3recki?= Date: Wed, 5 Jul 2017 09:17:22 +0200 Subject: [PATCH 12/12] Added invalid flags' usage error message --- colorls.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/colorls.rb b/colorls.rb index 499c75c..454869b 100755 --- a/colorls.rb +++ b/colorls.rb @@ -192,6 +192,14 @@ sort_dirs_first = args.include?('-sd') || args.include?('--sort-dirs') show_files_only = args.include?('-f') || args.include?('--files') show_dirs_only = args.include?('-d') || args.include?('--dirs') +if sort_dirs_first && sort_files_first + raise ArgumentError, 'Restrain from using -sd and -sf flags together' +end + +if show_files_only && show_dirs_only + raise ArgumentError, 'Restrain from using -d and -f flags together' +end + sort = if sort_files_first 'files' elsif sort_dirs_first