From 5f5d235775df751994abc8a965fcc7bb8b6f3c2d Mon Sep 17 00:00:00 2001 From: Agent K Date: Mon, 29 Apr 2024 11:35:00 +0300 Subject: [PATCH] Add --df, --dots-first option to sort dot-files and dot-folders first --- .gitignore | 1 + README.md | 1 + colorls.gemspec | 2 + lib/colorls/core.rb | 28 ++++- lib/colorls/flags.rb | 15 +-- man/colorls.1 | 211 ++++++++++++++++++++++++++++++++++++ spec/color_ls/flags_spec.rb | 10 ++ test/checks | 3 + zsh/_colorls | 60 ++++++++++ 9 files changed, 318 insertions(+), 13 deletions(-) create mode 100644 man/colorls.1 create mode 100644 zsh/_colorls diff --git a/.gitignore b/.gitignore index b4d6295e..ebbad358 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ pkg/ *.gem .bundle/ .yardoc/ +.vscode/ Gemfile.lock /_yardoc/ *.DS_store diff --git a/README.md b/README.md index 117ca2f9..e5b5e8f5 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ A Ruby script that colorizes the `ls` output with color and icons. Here are the - `--gs` (or) `--git-status` - `--sd` (or) `--sort-dirs` or `--group-directories-first` - `--sf` (or) `--sort-files` + - `--df` (or) `--dots-first` - `-t` - [Combination of flags](#combination-of-flags) - [Installation](#installation) diff --git a/colorls.gemspec b/colorls.gemspec index 0a7b5e46..9d6069b2 100644 --- a/colorls.gemspec +++ b/colorls.gemspec @@ -12,6 +12,8 @@ POST_INSTALL_MESSAGE = %( Sort by files : -sf flag has been renamed to --sf Git status : -gs flag has been renamed to --gs + Sort Dots First: --df, --dots-first - sort dot-files and dot-folders first + Clubbed flags : `colorls -ald` works Help menu : `colorls -h` provides all possible flag options diff --git a/lib/colorls/core.rb b/lib/colorls/core.rb index 89a647f6..d596b240 100644 --- a/lib/colorls/core.rb +++ b/lib/colorls/core.rb @@ -196,22 +196,38 @@ def filter_contents def sort_contents case @sort when :extension - @contents.sort_by! do |f| - name = f.name - ext = File.extname(name) - name = name.chomp(ext) unless ext.empty? - [ext, name].map { |s| CLocale.strxfrm(s) } - end + sort_by_extension when :time @contents.sort_by! { |a| -a.mtime.to_f } when :size @contents.sort_by! { |a| -a.size } + when :df + sort_by_dot_first else @contents.sort_by! { |a| CLocale.strxfrm(a.name) } end @contents.reverse! if @reverse end + def sort_by_extension + @contents.sort_by! do |f| + name = f.name + ext = File.extname(name) + name = name.chomp(ext) unless ext.empty? + [ext, name].map { |s| CLocale.strxfrm(s) } + end + end + + def sort_by_dot_first + @contents.sort_by! do |a| + name = a.name + # Check if the name starts with a dot + dot_prefix = name.start_with?('.') ? 0 : 1 + # Return an array where dot-prefixed names are sorted first + [dot_prefix, CLocale.strxfrm(name)] + end + end + def group_contents return unless @group diff --git a/lib/colorls/flags.rb b/lib/colorls/flags.rb index 92379ac2..e7857d1b 100644 --- a/lib/colorls/flags.rb +++ b/lib/colorls/flags.rb @@ -116,23 +116,24 @@ def add_sort_options(options) options.separator '' options.separator 'sorting options:' options.separator '' + configure_sort_options(options) + end + + def configure_sort_options(options) options.on('--sd', '--sort-dirs', '--group-directories-first', 'sort directories first') { @opts[:group] = :dirs } options.on('--sf', '--sort-files', 'sort files first') { @opts[:group] = :files } + options.on('--df', '--dots-first', 'sort dot-files and dot-folders first') { @opts[:sort] = :df } options.on('-t', 'sort by modification time, newest first') { @opts[:sort] = :time } options.on('-U', 'do not sort; list entries in directory order') { @opts[:sort] = false } options.on('-S', 'sort by file size, largest first') { @opts[:sort] = :size } options.on('-X', 'sort by file extension') { @opts[:sort] = :extension } options.on( '--sort=WORD', - %w[none time size extension], - 'sort by WORD instead of name: none, size (-S), time (-t), extension (-X)' + %w[none time size extension df], + 'sort by WORD instead of name: none, size (-S), time (-t), extension (-X), df (--df)' ) do |word| - @opts[:sort] = case word - when 'none' then false - else word.to_sym - end + @opts[:sort] = (word == 'none' ? false : word.to_sym) end - options.on('-r', '--reverse', 'reverse order while sorting') { @opts[:reverse] = true } end diff --git a/man/colorls.1 b/man/colorls.1 new file mode 100644 index 00000000..dd89c983 --- /dev/null +++ b/man/colorls.1 @@ -0,0 +1,211 @@ +.\" generated with Ronn/v0.7.3 +.\" http://github.com/rtomayko/ronn/tree/0.7.3 +. +.TH "COLORLS" "1" "April 2024" "colorls 1.5.0" "colorls Manual" +. +.SH "NAME" +\fBcolorls\fR \- list directory contents with colors and icons +. +.SH "SYNOPSIS" +\fBcolorls\fR [OPTION]\.\.\. [FILE]\.\.\. +. +.br +. +.SH "DESCRIPTION" +List information about the given FILEs\. Uses different colors and icons for known file types\. +. +.P +By default, the output is sorted alphabetically\. +. +.P +Mandatory arguments to long options are mandatory for short options too\. +. +.SH "OPTIONS" +. +.TP +\fB\-a\fR, \fB\-\-all\fR +do not ignore entries starting with \. +. +.TP +\fB\-A\fR, \fB\-\-almost\-all\fR +do not list \. and \.\. +. +.TP +\fB\-d\fR, \fB\-\-dirs\fR +show only directories +. +.TP +\fB\-f\fR, \fB\-\-files\fR +show only files +. +.TP +\fB\-\-gs\fR, \fB\-\-git\-status\fR +show git status for each file +. +.TP +\fB\-p\fR +append / indicator to directories +. +.TP +\fB\-i\fR, \fB\-\-inode\fR +show inode number +. +.TP +\fB\-\-report\fR +show report: short, long (default if omitted) +. +.TP +\fB\-\-indicator\-style\fR +append indicator with style STYLE to entry names: none, slash (\-p) (default) +. +.TP +\fB\-\-format\fR +use format: across (\-x), horizontal (\-x), long (\-l), single\-column (\-1), vertical (\-C) +. +.TP +\fB\-1\fR +list one file per line +. +.TP +\fB\-\-tree\fR +shows tree view of the directory +. +.TP +\fB\-x\fR +list entries by lines instead of by columns +. +.TP +\fB\-C\fR +list entries by columns instead of by lines +. +.TP +\fB\-\-without\-icons\fR +list entries without icons +. +.TP +\fB\-l\fR, \fB\-\-long\fR +use a long listing format +. +.TP +\fB\-o\fR +use a long listing format without group information +. +.TP +\fB\-g\fR +use a long listing format without owner information +. +.TP +\fB\-G\fR, \fB\-\-no\-group\fR +show no group information in a long listing +. +.TP +\fB\-\-time\-style\fR +use time display format +. +.TP +\fB\-\-no\-hardlinks\fR +show no hard links count in a long listing +. +.TP +\fB\-L\fR +show information on the destination of symbolic links +. +.TP +\fB\-\-non\-human\-readable\fR +show file sizes in bytes only +. +.TP +\fB\-\-sd\fR, \fB\-\-sort\-dirs\fR, \fB\-\-group\-directories\-first\fR +sort directories first +. +.TP +\fB\-\-sf\fR, \fB\-\-sort\-files\fR +sort files first +. +.TP +\fB\-\-df\fR, \fB\-\-dots\-first\fR +sort dot\-files and dot\-folders first +. +.TP +\fB\-t\fR +sort by modification time, newest first +. +.TP +\fB\-U\fR +do not sort; list entries in directory order +. +.TP +\fB\-S\fR +sort by file size, largest first +. +.TP +\fB\-X\fR +sort by file extension +. +.TP +\fB\-\-sort\fR +sort by WORD instead of name: none, size (\-S), time (\-t), extension (\-X), df (\-\-df) +. +.TP +\fB\-r\fR, \fB\-\-reverse\fR +reverse order while sorting +. +.TP +\fB\-h\fR, \fB\-\-human\-readable\fR: + +. +.TP +\fB\-\-color\fR +colorize the output: auto, always (default if omitted), never +. +.TP +\fB\-\-light\fR +use light color scheme +. +.TP +\fB\-\-dark\fR +use dark color scheme +. +.TP +\fB\-\-hyperlink\fR: + +. +.TP +\fB\-\-help\fR +prints this help +. +.TP +\fB\-\-version\fR +show version +. +.SH "EXAMPLES" +. +.TP +show the given file: +. +.IP +\fBcolorls README\.md\fR +. +.TP +show matching files and list matching directories: +. +.IP +\fBcolorls *\fR +. +.TP +filter output by a regular expression: +. +.IP +\fBcolorls | grep PATTERN\fR +. +.TP +several short options can be combined: +. +.IP +\fBcolorls \-d \-l \-a\fR +. +.br +\fBcolorls \-dla\fR +. +.SH "AUTHOR" +Written by Athitya Kumar\. diff --git a/spec/color_ls/flags_spec.rb b/spec/color_ls/flags_spec.rb index d09b1f61..69188582 100644 --- a/spec/color_ls/flags_spec.rb +++ b/spec/color_ls/flags_spec.rb @@ -195,6 +195,16 @@ end end + context 'with --sort=df flag' do + let(:args) { ['--sort=df', '--group-directories-first', '-1', FIXTURES] } + + it 'sort dot-files and dot-folders first' do + allow($stdout).to receive(:tty?).and_return(true) + + expect { subject }.to output(/symlinks.+a-file.+z-file/m).to_stdout + end + end + context 'with --help flag' do let(:args) { ['--help', FIXTURES] } diff --git a/test/checks b/test/checks index 9df9f6cd..e4471de0 100644 --- a/test/checks +++ b/test/checks @@ -15,6 +15,9 @@ OK colorls -r OK colorls --sd OK colorls --sf +OK colorls -laA --df +OK colorls -laA --dots-first +OK colorls -laA --sort=df OK colorls --hyperlink OK colorls -t OK colorls --sort=time diff --git a/zsh/_colorls b/zsh/_colorls new file mode 100644 index 00000000..1e5b1a10 --- /dev/null +++ b/zsh/_colorls @@ -0,0 +1,60 @@ +#compdef colorls + +typeset -A opt_args +local context state line + +_arguments -s -S \ + "-a[do not ignore entries starting with .]" \ + "--all[do not ignore entries starting with .]" \ + "-A[do not list . and ..]" \ + "--almost-all[do not list . and ..]" \ + "-d[show only directories]" \ + "--dirs[show only directories]" \ + "-f[show only files]" \ + "--files[show only files]" \ + "--gs[show git status for each file]" \ + "--git-status[show git status for each file]" \ + "-p[append / indicator to directories]" \ + "-i[show inode number]" \ + "--inode[show inode number]" \ + "--report[show report: short, long (default if omitted)]" \ + "--indicator-style[append indicator with style STYLE to entry names: none, slash (-p) (default)]" \ + "--format[use format: across (-x), horizontal (-x), long (-l), single-column (-1), vertical (-C)]" \ + "-1[list one file per line]" \ + "--tree[shows tree view of the directory]" \ + "-x[list entries by lines instead of by columns]" \ + "-C[list entries by columns instead of by lines]" \ + "--without-icons[list entries without icons]" \ + "-l[use a long listing format]" \ + "--long[use a long listing format]" \ + "-o[use a long listing format without group information]" \ + "-g[use a long listing format without owner information]" \ + "-G[show no group information in a long listing]" \ + "--no-group[show no group information in a long listing]" \ + "--time-style[use time display format]" \ + "--no-hardlinks[show no hard links count in a long listing]" \ + "-L[show information on the destination of symbolic links]" \ + "--non-human-readable[show file sizes in bytes only]" \ + "--sd[sort directories first]" \ + "--sort-dirs[sort directories first]" \ + "--group-directories-first[sort directories first]" \ + "--sf[sort files first]" \ + "--sort-files[sort files first]" \ + "--df[sort dot-files and dot-folders first]" \ + "--dots-first[sort dot-files and dot-folders first]" \ + "-t[sort by modification time, newest first]" \ + "-U[do not sort; list entries in directory order]" \ + "-S[sort by file size, largest first]" \ + "-X[sort by file extension]" \ + "--sort[sort by WORD instead of name: none, size (-S), time (-t), extension (-X), df (--df)]" \ + "-r[reverse order while sorting]" \ + "--reverse[reverse order while sorting]" \ + "-h[]" \ + "--human-readable[]" \ + "--color[colorize the output: auto, always (default if omitted), never]" \ + "--light[use light color scheme]" \ + "--dark[use dark color scheme]" \ + "--hyperlink[]" \ + "--help[prints this help]" \ + "--version[show version]" \ + '*:file:_files' && return 0