From cb59ed771ada1c7cec4231d959f3cf1f2610f99c Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Wed, 5 Jun 2024 10:19:21 -0400 Subject: [PATCH 1/8] initial basic qdls implementation --- qdls/.gitignore | 4 ++++ qdls/Program.cs | 42 ++++++++++++++++++++++++++++++++++++++++++ qdls/qdls.csproj | 10 ++++++++++ 3 files changed, 56 insertions(+) create mode 100644 qdls/.gitignore create mode 100644 qdls/Program.cs create mode 100644 qdls/qdls.csproj diff --git a/qdls/.gitignore b/qdls/.gitignore new file mode 100644 index 0000000..f57e698 --- /dev/null +++ b/qdls/.gitignore @@ -0,0 +1,4 @@ +obj/ +bin/ +.idea/ + diff --git a/qdls/Program.cs b/qdls/Program.cs new file mode 100644 index 0000000..71cbabc --- /dev/null +++ b/qdls/Program.cs @@ -0,0 +1,42 @@ +using System.IO; + +string[] arguments; +if(args.Length == 0) + arguments = ["."]; +else + arguments = args; +foreach(var arg in arguments) { + if(!Path.Exists(arg)) + Console.WriteLine($"'{arg}: does not exist"); + if(File.Exists(arg)) + Console.WriteLine($"'{arg}: is file"); + + var children = Directory.GetFileSystemEntries(arg); + + var line = ""; + var longest = children.OrderByDescending(s => Path.GetFileName(s).Length).First().Length; + var columns = Console.WindowWidth / (longest + 2); + var position = -1; + + if(args.Length > 1) + Console.WriteLine($"{arg}:"); + foreach(var child in children) { + var name = Path.GetFileName(child); + + if( + name.StartsWith('.') || + ( File.GetAttributes(child) & FileAttributes.Hidden ) == FileAttributes.Hidden + ) + continue; + + if(++position >= columns) { + position = -1; + Console.WriteLine(line); + line = ""; + } + line += name + " "; + + } + + Console.WriteLine(line); +} diff --git a/qdls/qdls.csproj b/qdls/qdls.csproj new file mode 100644 index 0000000..206b89a --- /dev/null +++ b/qdls/qdls.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + From 9591a4867c7e52668511e43deafe01d5e48e4df5 Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Fri, 7 Jun 2024 14:11:14 -0400 Subject: [PATCH 2/8] improved formatting and code readability --- qdls/Program.cs | 46 +++++++++++++++++++++++++++++++++++----------- qdls/Util.cs | 24 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 qdls/Util.cs diff --git a/qdls/Program.cs b/qdls/Program.cs index 71cbabc..ef7d0c7 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -1,42 +1,66 @@ using System.IO; +using Qdls; + +// collect args; no args becomes working directory string[] arguments; if(args.Length == 0) arguments = ["."]; else arguments = args; + +// flags +bool showHidden = true; + +// run on targets foreach(var arg in arguments) { + // don't try to list nonexistent entries or files if(!Path.Exists(arg)) Console.WriteLine($"'{arg}: does not exist"); if(File.Exists(arg)) Console.WriteLine($"'{arg}: is file"); + // fetch children var children = Directory.GetFileSystemEntries(arg); - var line = ""; + // state vars + var buffer = ""; var longest = children.OrderByDescending(s => Path.GetFileName(s).Length).First().Length; var columns = Console.WindowWidth / (longest + 2); + var multiline = columns < args.Length; var position = -1; + // print names if more than one target if(args.Length > 1) Console.WriteLine($"{arg}:"); + // iterate over children; build buffer and output when full foreach(var child in children) { var name = Path.GetFileName(child); - if( - name.StartsWith('.') || - ( File.GetAttributes(child) & FileAttributes.Hidden ) == FileAttributes.Hidden - ) - continue; + // skip or format hidden files + if(Util.IsHidden(child)) + if(showHidden) + buffer += Format.Hidden; + else + continue; - if(++position >= columns) { + // format directories + if(Directory.Exists(child)) + buffer += Format.Directory; + + // if we pass max width, write buffer and clear + if( multiline && (++position > columns) ) { position = -1; - Console.WriteLine(line); - line = ""; + Console.WriteLine(buffer); + buffer = ""; } - line += name + " "; + if(multiline) + buffer += $"{name}{Format.Reset}".PadRight(longest) + " "; + else + buffer += $"{name}{Format.Reset} "; } - Console.WriteLine(line); + // print last line + Console.WriteLine(buffer); } diff --git a/qdls/Util.cs b/qdls/Util.cs new file mode 100644 index 0000000..6b3200a --- /dev/null +++ b/qdls/Util.cs @@ -0,0 +1,24 @@ +namespace Qdls; + +using System.IO; + +public static class Util { + + public static bool IsHidden(string path) { + var name = Path.GetFileName(path); + return + name.StartsWith('.') || + ( File.GetAttributes(path) & FileAttributes.Hidden ) == FileAttributes.Hidden; + } + +} + +public static class Format { + + public const string Reset = "\x1b[0m"; // reset + public const string Hidden = "\x1b[2;3m"; // faint + italic + public const string Executable = "\x1b[1;32m"; // bold + green + public const string Directory = "\x1b[1;34m"; // bold + blue + +} + From cf7c78569cb814545653da31610a2d82152c6ad8 Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Fri, 7 Jun 2024 14:11:24 -0400 Subject: [PATCH 3/8] updated README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 8c8ca23..f78d290 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,7 @@ paths like missing support for symbolic links, mismatched path separators, inability to handle spaces in directory names, and resolves C-drive paths to their normal DOS form. +## `qdls` + +A DOS clone of `ls` that hides Windows hidden files. + From 6f61a98ebc27666b64aedee5c7b140ebb1f8fb25 Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Fri, 7 Jun 2024 15:17:18 -0400 Subject: [PATCH 4/8] better hidden file handling --- qdls/Program.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/qdls/Program.cs b/qdls/Program.cs index ef7d0c7..9dd3bb1 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -1,5 +1,4 @@ -using System.IO; - + using Qdls; // collect args; no args becomes working directory @@ -10,7 +9,7 @@ else arguments = args; // flags -bool showHidden = true; +bool showHidden = false; // run on targets foreach(var arg in arguments) { @@ -22,6 +21,7 @@ foreach(var arg in arguments) { // fetch children var children = Directory.GetFileSystemEntries(arg); + if(!showHidden) { children = children.Where(f => !Util.IsHidden(f)).ToArray(); } // state vars var buffer = ""; @@ -39,10 +39,7 @@ foreach(var arg in arguments) { // skip or format hidden files if(Util.IsHidden(child)) - if(showHidden) - buffer += Format.Hidden; - else - continue; + buffer += Format.Hidden; // format directories if(Directory.Exists(child)) From 1b42869e3f5a12d47bde1eea4d3165c3b81966f6 Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Mon, 10 Jun 2024 09:53:43 -0400 Subject: [PATCH 5/8] show hidden flag implemented --- qdls/Program.cs | 18 +++++++++--------- qdls/Util.cs | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/qdls/Program.cs b/qdls/Program.cs index 9dd3bb1..1a83465 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -1,15 +1,14 @@  using Qdls; -// collect args; no args becomes working directory -string[] arguments; -if(args.Length == 0) - arguments = ["."]; -else - arguments = args; +// collect args and consume flags +List arguments = args.ToList(); -// flags -bool showHidden = false; +bool showHidden = Util.CheckFlag(arguments, "-a", "--all", "-A"); + +// default to "." if no target args +if(arguments.Count == 0) + arguments = ["."]; // run on targets foreach(var arg in arguments) { @@ -21,6 +20,7 @@ foreach(var arg in arguments) { // fetch children var children = Directory.GetFileSystemEntries(arg); + // exclude hidden files where applicable if(!showHidden) { children = children.Where(f => !Util.IsHidden(f)).ToArray(); } // state vars @@ -37,7 +37,7 @@ foreach(var arg in arguments) { foreach(var child in children) { var name = Path.GetFileName(child); - // skip or format hidden files + // format hidden files if(Util.IsHidden(child)) buffer += Format.Hidden; diff --git a/qdls/Util.cs b/qdls/Util.cs index 6b3200a..103f34c 100644 --- a/qdls/Util.cs +++ b/qdls/Util.cs @@ -11,6 +11,11 @@ public static class Util { ( File.GetAttributes(path) & FileAttributes.Hidden ) == FileAttributes.Hidden; } + public static bool CheckFlag(List args, params string[] forms) { + var found = args.RemoveAll(forms.Contains); + return found > 0; + } + } public static class Format { From 763ccb3291170b84905941949c638d17d4db369c Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Mon, 10 Jun 2024 13:05:12 -0400 Subject: [PATCH 6/8] fixed column behavior in qdls --- qdls/Program.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/qdls/Program.cs b/qdls/Program.cs index 1a83465..6c1aa17 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -1,5 +1,4 @@ - -using Qdls; +using Qdls; // collect args and consume flags List arguments = args.ToList(); @@ -25,10 +24,10 @@ foreach(var arg in arguments) { // state vars var buffer = ""; - var longest = children.OrderByDescending(s => Path.GetFileName(s).Length).First().Length; + var longest = Path.GetFileName(children.OrderByDescending(s => s.Length).First()).Length; var columns = Console.WindowWidth / (longest + 2); - var multiline = columns < args.Length; - var position = -1; + var multiline = columns < children.Count(); + var position = 0; // print names if more than one target if(args.Length > 1) @@ -46,13 +45,13 @@ foreach(var arg in arguments) { buffer += Format.Directory; // if we pass max width, write buffer and clear - if( multiline && (++position > columns) ) { - position = -1; - Console.WriteLine(buffer); + if( (++position > columns) && multiline ) { + position = 1; + Console.WriteLine(buffer.TrimEnd()); buffer = ""; } if(multiline) - buffer += $"{name}{Format.Reset}".PadRight(longest) + " "; + buffer += $"{name}{Format.Reset}".PadRight(longest + 4); else buffer += $"{name}{Format.Reset} "; From 02399fecdb76e5d548830b5a8c01f85ec80d4f8b Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Mon, 10 Jun 2024 13:22:14 -0400 Subject: [PATCH 7/8] qdls: fixed skip cases not skipping and order is more like ls --- qdls/Program.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/qdls/Program.cs b/qdls/Program.cs index 6c1aa17..5f60b61 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -12,10 +12,14 @@ if(arguments.Count == 0) // run on targets foreach(var arg in arguments) { // don't try to list nonexistent entries or files - if(!Path.Exists(arg)) - Console.WriteLine($"'{arg}: does not exist"); - if(File.Exists(arg)) - Console.WriteLine($"'{arg}: is file"); + if(!Path.Exists(arg)) { + Console.WriteLine($"'{arg}': does not exist"); + continue; + } + if(File.Exists(arg)) { + Console.WriteLine($"'{arg}': is file"); + continue; + } // fetch children var children = Directory.GetFileSystemEntries(arg); @@ -33,7 +37,7 @@ foreach(var arg in arguments) { if(args.Length > 1) Console.WriteLine($"{arg}:"); // iterate over children; build buffer and output when full - foreach(var child in children) { + foreach(var child in children.OrderBy(f => (int)(Path.GetFileName(f)[0]))) { var name = Path.GetFileName(child); // format hidden files From ab20175cf0ba8136fcf7baa1a1b269b91186912c Mon Sep 17 00:00:00 2001 From: Valerie Wolfe Date: Mon, 10 Jun 2024 13:34:59 -0400 Subject: [PATCH 8/8] fixed qdls formatting --- qdls/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qdls/Program.cs b/qdls/Program.cs index 5f60b61..9ec5455 100644 --- a/qdls/Program.cs +++ b/qdls/Program.cs @@ -55,7 +55,7 @@ foreach(var arg in arguments) { buffer = ""; } if(multiline) - buffer += $"{name}{Format.Reset}".PadRight(longest + 4); + buffer += $"{name}{Format.Reset}".PadRight(longest + 6); // magic number 6 is +2 ignoring ansi reset sequence else buffer += $"{name}{Format.Reset} ";