Skip to content

Commit 9963708

Browse files
committed
feat(ls): add Python implementation with color support for directories
- Implement ls/ls.py: Python version of ls utility - Add -1/--one-per-line flag for single column output - Add -a/--all flag to show hidden files (dotfiles) - Color directories in blue using ANSI escape codes - Sort entries case-insensitively for better readability - Support custom directory path argument (default to current directory) - Add error handling with proper exit codes - Match behavior of JavaScript implementation
1 parent c54ba92 commit 9963708

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

implement-shell-tools/cat/cat.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import sys
2+
import argparse
3+
4+
def read_and_output_files():
5+
# 1. Setup Argument Parser (Equivalent to 'commander')
6+
parser = argparse.ArgumentParser(description="Python implementation of a basic cat-like utility")
7+
parser.add_argument("-n", "--number", action="store_true", help="number all output lines")
8+
parser.add_argument("-b", "--number-nonblank", action="store_true", help="number only non-empty lines")
9+
parser.add_argument("files", nargs="+", help="files to read")
10+
11+
args = parser.parse_args()
12+
13+
try:
14+
# 2. Read all file contents (Equivalent to Promise.all / fs.readFile)
15+
file_contents = []
16+
for file_path in args.files:
17+
with open(file_path, "r", encoding="utf-8") as f:
18+
file_contents.append(f.read())
19+
20+
concatenated_content = "".join(file_contents)
21+
22+
# 3. Process Logic
23+
if args.number:
24+
# -n logic: number all lines
25+
lines = concatenated_content.split("\n")
26+
output = []
27+
for index, line in enumerate(lines, start=1):
28+
# rjust(6) is equivalent to padStart(6)
29+
output.append(f"{str(index).rjust(6)} {line}")
30+
sys.stdout.write("\n".join(output))
31+
32+
elif args.number_nonblank:
33+
# -b logic: number only non-empty lines
34+
lines = concatenated_content.split("\n")
35+
output = []
36+
nonblank_line_number = 0
37+
for line in lines:
38+
if line.strip() == "":
39+
output.append(line)
40+
else:
41+
nonblank_line_number += 1
42+
output.append(f"{str(nonblank_line_number).rjust(6)} {line}")
43+
sys.stdout.write("\n".join(output))
44+
45+
else:
46+
# No flags: standard output
47+
sys.stdout.write(concatenated_content)
48+
49+
except Exception as err:
50+
print(f"Error reading multiple files: {err}", file=sys.stderr)
51+
sys.exit(1)
52+
53+
if __name__ == "__main__":
54+
read_and_output_files()

implement-shell-tools/ls/ls.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import os
2+
import sys
3+
import argparse
4+
5+
def run_ls_command():
6+
parser = argparse.ArgumentParser()
7+
parser.add_argument("-1", "--one-per-line", action="store_true", dest="one")
8+
parser.add_argument("-a", "--all", action="store_true")
9+
parser.add_argument("path", nargs="?", default=".")
10+
args = parser.parse_args()
11+
12+
# ANSI Color Codes
13+
BLUE = '\033[34m'
14+
RESET = '\033[0m'
15+
16+
try:
17+
# 1. Get and sort entries
18+
directory_entries = os.listdir(args.path)
19+
directory_entries.sort(key=str.lower)
20+
21+
# 2. Filter out dotfiles unless -a is used
22+
visible_entries = []
23+
if args.all:
24+
visible_entries = directory_entries
25+
else:
26+
for name in directory_entries:
27+
if not name.startswith("."):
28+
visible_entries.append(name)
29+
30+
# 3. Apply colors to folders
31+
colored_entries = []
32+
for name in visible_entries:
33+
# We must join the path to the name to check if it's a folder correctly
34+
full_path = os.path.join(args.path, name)
35+
36+
if os.path.isdir(full_path):
37+
# Wrap the name in Blue color codes
38+
colored_entries.append(f"{BLUE}{name}{RESET}")
39+
else:
40+
# Keep regular file name as is
41+
colored_entries.append(name)
42+
43+
# 4. Build output string
44+
output_string = ""
45+
if args.one:
46+
output_string = "\n".join(colored_entries) + "\n"
47+
else:
48+
output_string = " ".join(colored_entries) + "\n"
49+
50+
if colored_entries:
51+
sys.stdout.write(output_string)
52+
53+
except Exception as err:
54+
print(f"Error: {err}", file=sys.stderr)
55+
sys.exit(1)
56+
57+
if __name__ == "__main__":
58+
run_ls_command()

0 commit comments

Comments
 (0)