Remove comments from python files.
This commit is contained in:
parent
daf77f0ba2
commit
00b5d2d903
53
pf.py
Executable file
53
pf.py
Executable file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import tokenize
|
||||
import io
|
||||
import sys
|
||||
|
||||
def remove_comments_from_code(source_code):
|
||||
tokens = tokenize.generate_tokens(io.StringIO(source_code).readline)
|
||||
tokens_no_comments = [
|
||||
token for token in tokens if token.type != tokenize.COMMENT
|
||||
]
|
||||
return tokenize.untokenize(tokens_no_comments)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Remove all comments from a Python file using tokenize.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'input_file',
|
||||
help='Path to the target Python file.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'output_file',
|
||||
nargs='?',
|
||||
help='Path to save the cleaned Python file. If omitted, prints to stdout.'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
with open(args.input_file, 'r', encoding='utf-8') as f:
|
||||
source_code = f.read()
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {args.input_file}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
cleaned_code = remove_comments_from_code(source_code)
|
||||
|
||||
if args.output_file:
|
||||
try:
|
||||
with open(args.output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(cleaned_code)
|
||||
except Exception as e:
|
||||
print(f"Error writing file: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(cleaned_code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
42
shortcuts.py
42
shortcuts.py
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
vim_terminal_trainer.py – *v2*
|
||||
================================
|
||||
@ -35,7 +35,7 @@ import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
# ------------------- DATA & CONFIG -----------------------------------------
|
||||
|
||||
|
||||
DEFAULT_QUESTIONS: List[Dict[str, object]] = [
|
||||
{"task": "Delete (cut) the current line in Vim", "answers": ["dd"]},
|
||||
@ -462,7 +462,7 @@ TIME_LIMIT_SEC = 15
|
||||
DATA_DIR = Path.home() / ".vim_terminal_trainer"
|
||||
SCORE_FILE = DATA_DIR / "score.json"
|
||||
|
||||
# ------------------- PERSISTENCE -------------------------------------------
|
||||
|
||||
|
||||
|
||||
def load_score() -> Dict[str, int]:
|
||||
@ -485,7 +485,7 @@ def save_score(high: int, played: int) -> None:
|
||||
json.dump({"high_score": high, "games_played": played}, f)
|
||||
|
||||
|
||||
# ------------------- CURSES UI HELPERS -------------------------------------
|
||||
|
||||
|
||||
|
||||
def draw_centered(
|
||||
@ -506,7 +506,7 @@ def render_timer(stdscr: "curses._CursesWindow", remaining: float) -> None:
|
||||
stdscr.addstr(0, 0, f"⏰[{bar}] {remaining:4.1f}s")
|
||||
|
||||
|
||||
# ------------------- GAMEPLAY ----------------------------------------------
|
||||
|
||||
def sanitize_question(q):
|
||||
"""Return a dict with keys 'task' and 'answers' no matter what comes in."""
|
||||
if isinstance(q, dict):
|
||||
@ -524,20 +524,20 @@ def ask_question_curses(
|
||||
idx: int,
|
||||
total: int,
|
||||
) -> bool:
|
||||
q = sanitize_question(q) # ← new – normalise input
|
||||
q = sanitize_question(q)
|
||||
stdscr.clear()
|
||||
h, w = stdscr.getmaxyx()
|
||||
|
||||
# Header
|
||||
|
||||
header = f"Question {idx}/{total} – Type the command:"
|
||||
draw_centered(stdscr, 2, header, bold=True)
|
||||
|
||||
# Task text (wrapped)
|
||||
|
||||
wrapped = textwrap.fill(q["task"], width=min(70, w - 4))
|
||||
for i, line in enumerate(wrapped.splitlines(), start=4):
|
||||
draw_centered(stdscr, i, line)
|
||||
|
||||
# Input prompt area
|
||||
|
||||
input_y = 6 + wrapped.count("\n")
|
||||
stdscr.addstr(input_y, 2, "› ")
|
||||
stdscr.refresh()
|
||||
@ -558,46 +558,46 @@ def ask_question_curses(
|
||||
if remaining <= 0:
|
||||
return False
|
||||
|
||||
# Non‑blocking read (100 ms chunks)
|
||||
|
||||
stdscr.timeout(100)
|
||||
ch = stdscr.getch()
|
||||
if ch == -1:
|
||||
continue # no keypress yet
|
||||
continue
|
||||
if ch in (curses.KEY_BACKSPACE, 127, 8):
|
||||
buffer = buffer[:-1]
|
||||
continue
|
||||
if ch in (10, 13):
|
||||
# User pressed Return anyway – treat as submission
|
||||
|
||||
break
|
||||
if 0 <= ch <= 255:
|
||||
buffer += chr(ch)
|
||||
|
||||
# Auto‑check
|
||||
|
||||
norm = " ".join(buffer.split())
|
||||
if norm in valid:
|
||||
# Flash feedback
|
||||
|
||||
curses.curs_set(0)
|
||||
stdscr.addstr(input_y + 1, 4, "✅ Correct!", curses.A_BOLD)
|
||||
stdscr.refresh()
|
||||
time.sleep(0.4)
|
||||
return True
|
||||
# Trim oversized buffer to keep UI tidy
|
||||
|
||||
if len(buffer) > longest + 5:
|
||||
buffer = buffer[-(longest + 5) :]
|
||||
|
||||
# Manual submission (Return) or timeout
|
||||
|
||||
norm = " ".join(buffer.split())
|
||||
return norm in valid
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
def play_game(stdscr: "curses._CursesWindow", pool: List[Dict[str, object]]) -> None:
|
||||
score_data = load_score()
|
||||
curses.curs_set(0)
|
||||
|
||||
# Ask number of questions (simple prompt outside curses because of text input)
|
||||
|
||||
curses.endwin()
|
||||
try:
|
||||
q_default = 10 if len(pool) >= 10 else len(pool)
|
||||
@ -606,7 +606,7 @@ def play_game(stdscr: "curses._CursesWindow", pool: List[Dict[str, object]]) ->
|
||||
num_q = q_default
|
||||
num_q = max(1, min(num_q, len(pool)))
|
||||
|
||||
# Back into curses
|
||||
|
||||
stdscr = curses.initscr()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
@ -619,7 +619,7 @@ def play_game(stdscr: "curses._CursesWindow", pool: List[Dict[str, object]]) ->
|
||||
if ask_question_curses(stdscr, q, idx, num_q):
|
||||
correct += 1
|
||||
|
||||
# Final screen
|
||||
|
||||
stdscr.clear()
|
||||
result_text = f"You scored {correct}/{num_q}!"
|
||||
draw_centered(stdscr, 3, result_text, bold=True)
|
||||
@ -640,7 +640,7 @@ def play_game(stdscr: "curses._CursesWindow", pool: List[Dict[str, object]]) ->
|
||||
stdscr.getch()
|
||||
|
||||
|
||||
# ------------------- MAIN ---------------------------------------------------
|
||||
|
||||
|
||||
|
||||
def main_menu() -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user