-
-
Notifications
You must be signed in to change notification settings - Fork 42
London | 25-SDC-July | Franklin Kamela | Sprint 4 | Feature/shell-tools-python #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 10 commits
0611383
1f5b567
0a71087
72271cf
0d3bc17
22a04bb
32a3a87
4ef88e2
0e07af9
3770801
3022163
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "githubPullRequests.ignoredPullRequestBranches": [ | ||
| "main" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/usr/bin/env python3 | ||
| import argparse | ||
|
|
||
| # implement-shell-tools/cat/cat.py | ||
| def main(): | ||
| parser = argparse.ArgumentParser( | ||
| prog="cat", | ||
| description="Implements a simple version of the 'cat' command to read and display file contents." | ||
| ) | ||
|
|
||
| parser.add_argument("-n", help="Number lines", action="store_true") | ||
| parser.add_argument("-b", help="Number non-blank lines", action="store_true") | ||
| parser.add_argument("path", nargs="+", help="The file to search") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| line_number = 1 | ||
| non_blank_line_number = 1 | ||
|
|
||
| for file_path in args.path: | ||
| try: | ||
| with open(file_path, 'r') as file: | ||
| content = file.read() | ||
| lines = content.split("\n") | ||
|
|
||
| for i, line in enumerate(lines): | ||
| if i == len(lines) - 1 and line == "": # Skip the last empty line if it exists | ||
| break | ||
| prefix = "" | ||
| if args.n: | ||
| prefix = str(line_number).rjust(6) + " " | ||
| elif args.b and line != "": | ||
| prefix = str(non_blank_line_number).rjust(6) + " " | ||
| print(prefix + line) | ||
| line_number += 1 | ||
| if line != "": | ||
| non_blank_line_number += 1 | ||
|
|
||
| except FileNotFoundError: | ||
| print(f"cat: {file_path}: No such file or directory") | ||
| except Exception as e: | ||
| print(f"cat: {file_path}: {e}") | ||
|
|
||
| if __name__ == "__main__": | ||
| main() |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you tested to make sure your -1 argument is working correctly? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # implement-shell-tools/ls/ls.py | ||
| import argparse | ||
| import os | ||
| import sys | ||
| import shutil | ||
| import math | ||
|
|
||
| def print_columns(items, force_single_column=False): | ||
| """Print items in columns unless -1 is passed or output is not a tty.""" | ||
| if force_single_column or not sys.stdout.isatty(): | ||
| for item in items: | ||
| print(item) | ||
| return | ||
|
|
||
| # Get terminal width | ||
| term_width = shutil.get_terminal_size((80, 20)).columns | ||
|
|
||
| if not items: | ||
| return | ||
|
|
||
| # Longest filename length + spacing | ||
| max_len = max(len(f) for f in items) + 2 | ||
| cols = max(1, term_width // max_len) | ||
| rows = math.ceil(len(items) / cols) | ||
|
|
||
| for r in range(rows): | ||
| row_items = [] | ||
| for c in range(cols): | ||
| i = c * rows + r | ||
| if i < len(items): | ||
| row_items.append(items[i].ljust(max_len)) | ||
| print("".join(row_items).rstrip()) | ||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser( | ||
| prog="ls", | ||
| description="Implements a simple version of the 'ls' command to list files in a directory." | ||
| ) | ||
|
|
||
| parser.add_argument("-1", help="List one file per line", action="store_true") | ||
| parser.add_argument("-a", help="Include hidden files", action="store_true") | ||
| parser.add_argument("directory", nargs="?", default=".", help="The directory to search") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| try: | ||
| if os.path.isdir(args.directory): | ||
| files = os.listdir(args.directory) | ||
|
|
||
| if not args.a: | ||
| files = [f for f in files if not f.startswith(".")] | ||
|
|
||
| files = sorted(files) | ||
|
|
||
| print_columns(files, force_single_column=args.__dict__["1"]) | ||
| else: | ||
| # If it's a file, just print the name | ||
| print(args.directory) | ||
|
|
||
| except FileNotFoundError: | ||
| print(f"ls: {args.directory}: No such file or directory", file=sys.stderr) | ||
| except Exception as e: | ||
| print(f"ls: {args.directory}: {e}", file=sys.stderr) | ||
|
|
||
| if __name__ == "__main__": | ||
| main() |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is some duplication in this code, can you have a look at reducing it? Also, when you are outputting, make sure that the indentation is working right. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import argparse | ||
| import sys | ||
|
|
||
| # implement-shell-tools/wc/wc.py | ||
| def wc_file(path): | ||
| """Return (lines, words, bytes) for a given file.""" | ||
| with open(path, "r", encoding="utf-8") as f: | ||
| text = f.read() | ||
| lines = text.count("\n") | ||
| if text and not text.endswith("\n"): | ||
| lines += 1 # Count last line if it doesn't end with newline | ||
| words = len(text.split()) | ||
| chars = len(text.encode("utf-8")) # byte count | ||
| return lines, words, chars | ||
|
|
||
| def format_counts(lines, words, chars, args, label): | ||
| """Return formatted output string for wc counts.""" | ||
| parts = [] | ||
| if args.l: | ||
| parts.append(str(lines).rjust(8)) | ||
| if args.w: | ||
| parts.append(str(words).rjust(8)) | ||
| if args.c: | ||
| parts.append(str(chars).rjust(8)) | ||
| if label: | ||
| parts.append(label) | ||
| return " ".join(parts) | ||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser( | ||
| prog="wc", | ||
| description="Implements a simple version of the 'wc' command to count lines, words, and characters in text files." | ||
| ) | ||
|
|
||
| parser.add_argument("-l", action="store_true", help="Count lines") | ||
| parser.add_argument("-w", action="store_true", help="Count words") | ||
| parser.add_argument("-c", action="store_true", help="Count characters") | ||
| parser.add_argument("path", nargs="+", help="The files to read") | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| if not (args.l or args.w or args.c): | ||
| args.l = args.w = args.c = True # Default to all counts if none specified | ||
|
|
||
| total_lines = total_words = total_chars = 0 | ||
|
|
||
| for file_path in args.path: | ||
| try: | ||
| lines, words, chars = wc_file(file_path) | ||
| total_lines += lines | ||
| total_words += words | ||
| total_chars += chars | ||
|
|
||
| print(format_counts(lines, words, chars, args, file_path)) | ||
|
|
||
| except FileNotFoundError: | ||
| print(f"wc: {file_path}: No such file or directory", file=sys.stderr) | ||
| except Exception as e: | ||
| print(f"wc: {file_path}: {e}", file=sys.stderr) | ||
|
|
||
| if len(args.path) > 1: | ||
| print(format_counts(total_lines, total_words, total_chars, args, "total")) | ||
|
|
||
| if __name__ == "__main__": | ||
| main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tested that the numbering is working correctly when multiple files are passed in?