Update readme.

This commit is contained in:
retoor 2024-12-04 19:27:09 +01:00
parent bc574ba0a4
commit 5c8f307491
2 changed files with 1 additions and 309 deletions

View File

@ -7,7 +7,7 @@ Rtutor is an application written in python to train yourself to use vim fast way
- Repeat question on random moment if you answered it wrong. You have to learn! - Repeat question on random moment if you answered it wrong. You have to learn!
## Usage ## Usage
This application has no dependencies. Instead of cloning this git, you can just do wget or copy the raw source code of [rtutor.py](rtutor.py). This application has no dependencies. Instead of cloning this git, you can just do wget or copy the raw source code of [rvimtutor.py](rvimtutor.py).
``` ```
python3 rtutor.py python3 rtutor.py
``` ```

308
rtutor.py
View File

@ -1,308 +0,0 @@
#!/usr/bin/env python3
# RETOOR
import sys
import termios
import tty
import random
import time
import select
key_mapping = {
"[A": "up",
"[B": "down",
"[C": "right",
"[D": "left",
"2A": "shift+up",
"2B": "shift+down",
"2C": "shift+right",
"2D": "shift+left",
"5A": "ctrl+up",
"5B": "ctrl+down",
"5C": "ctrl+right",
"5D": "ctrl+left",
"\x17": "C-w",
"\x0f": "C-o",
"\x03": "C-c",
"\x07": "C-g",
}
def get_key(key_previous=None):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
special_char = "\x1b"
if key_previous is None:
key_previous = special_char
try:
tty.setraw(fd)
key = sys.stdin.read(1)
if key in key_mapping:
return key_mapping[key]
if key == "[":
key += sys.stdin.read(1)
if key in key_mapping:
return key_mapping.get(key, key)
if key[-1] == "1": # shift plus special key
if sys.stdin.read(1) == ";": # ;followed by key
key = sys.stdin.read(2)
return key_mapping.get(key, key)
if key == special_char:
time.sleep(0.1)
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
key += sys.stdin.read(2)
key = key_mapping.get(key, key)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return key
def clear_terminal():
sys.stdout.write("\033[2J")
# Move cursor
sys.stdout.write("\033[H")
sys.stdout.flush()
class Randoms:
input_choices = list("abcdefghijklmnopqrstuvwxyz")
word_choices = word_list = [
"apple",
"banana",
"cherry",
"date",
"elderberry",
"fig",
"grape",
"honeydew",
"kiwi",
"lemon",
"mango",
"nectarine",
"orange",
"pear",
"quince",
"raspberry",
"strawberry",
"tangerine",
"ugli",
"vaccine",
"watermelon",
"xigua",
"yam",
"zucchini",
]
def __init__(self):
self.replace = {}
self.replace["<randc1>"] = random.choice(self.input_choices)
self.replace["<randc2>"] = random.choice(self.input_choices)
self.replace["<randc3>"] = random.choice(self.input_choices)
self.replace["<rints1>"] = random.randint(2, 5)
self.replace["<rints2>"] = random.randint(2, 5)
self.replace["<rints3>"] = random.randint(2, 5)
self.replace["<w1>"] = random.choice(self.word_choices)
self.replace["<w2>"] = random.choice(self.word_choices)
self.replace["<w3>"] = random.choice(self.word_choices)
def apply(self, task):
task.question = task.base_question
task.keyboard_input = task.base_keyboard_input
for key, value in self.replace.items():
task.question = task.question.replace(key, str(value))
task.keyboard_input = task.keyboard_input.replace(
key, ",".join(list(str(value)))
)
task.applied_random = (
task.question != task.base_question
or task.keyboard_input != task.base_keyboard_input
)
class Task:
questions_total = 0
def __init__(self, question, keyboard_input):
Task.questions_total += 1
self.question_number = Task.questions_total
self.base_question = question
self.base_keyboard_input = keyboard_input
self.question = question
self.keyboard_input = keyboard_input
self.success = False
self.tasks = []
self.applied_random = False
self.first_time_executed = True
r = Randoms()
r.apply(self)
def add_task(self, task):
self.tasks.append(task)
def execute(self):
if not self.first_time_executed:
r = Randoms()
r.apply(self)
self.first_time_executed = False
print("{}".format(self.question))
index = 0
mistake = False
key_previous = None
for expected in self.keyboard_input.split(","):
key = get_key(key_previous)
key_previous = key
if key == "\x1b":
key = get_key(key_previous)
key_previous = key
if key == "C-c":
raise KeyboardInterrupt()
if key == "\x17":
print("CTRL+W")
else:
print(key, end="", flush=True)
if expected == key:
index += 1
else:
mistake = True
if mistake:
print('\n"{}" is incorrect.'.format(repr(key)))
print(
'\nExpected input: "{}".'.format(
self.keyboard_input.replace(",", "")
)
)
print("\nPress any key to continue...")
get_key(None)
break
if key == "q":
break
if not mistake:
self.success = True
print("")
print(
random.choice(
["Great!", "Excelent!", "Awesome!", "Keep it up!", "Perfect!"]
)
)
print("")
self.success = all([task.execute() for task in self.tasks])
time.sleep(0.40)
return self.success
tasks = [
Task("Open terminal\n", ":,terminal,\r"),
Task("Delete from the cursor to the end of the word.", "d,e"),
Task("Delete from the cursor to the end of the line.", "d,$"),
Task("Delete from the cursor to the beginning of the next word.", "d,w"),
Task("Delete <rints1> lines using a numeric value.", "<rints1>,d,d"),
Task("Move backward in the search results.", "N"),
Task("Move forward in the search results.", "n"),
Task("Move to line number <rints1>.", "<rints1>,G"),
Task("Undo all changes on the current line.", "U"),
Task("Move to the end of the word.", "e"),
Task("Move to the beginning of the line.", "0"),
Task("Search backward for <w1>.", ":,?,<w1>,\r"),
Task("Search forward for <w1>.", ":,/,<w1>,\r"),
Task("Display the current location in the status bar.", "C-g"),
Task("Indent the selected text.", ">,>"),
Task("De-indent the selected text.", "<,<"),
Task("Save the document as <w1>.py.", ":,w, ,<w1>,.,p,y,\r"),
Task("Replace the first occurrence of <w1> with <w2>.", ":,s,/,<w1>,/,<w2>,/,g"),
Task(
"Replace all occurrences of <w1> with <w2> in the entire file.",
":,%,s,/,<w1>,/,<w2>,/,g",
),
Task(
"Replace all occurrences of <w1> with <w2> in the entire file, with confirmation for each change.",
":,%,s,/,<w1>,/,<w2>,/,g,c",
),
Task(
"Select the next five characters and save them to a file.",
"v,right,right,right,right,:,w",
),
Task("Exit Vim.", ":,q"),
Task("Split the screen vertically.", ":,v,s,p,l,i,t,\r"),
Task("Split the screen horizontally.", ":,s,p,l,i,t,\r"),
Task("Merge the file <w1>.txt into the current file.", ":,r, ,<w1>,.,t,x,t,\r"),
Task(
"Move three words to the left without using numeric values.",
"ctrl+left,ctrl+left,ctrl+left",
),
Task(
"Move three words to the right without using numeric values.",
"ctrl+right,ctrl+right,ctrl+right",
),
Task("Return to the previous position.", "C-o"),
Task("Type <w1>.", "<w1>"),
Task("Indent the current line and the two lines below.", "v,down,down,>,>"),
Task("Enable case-sensitive search.", ":,s,e,t, ,n,o,i,c"),
Task("Enable case-insensitive search.", ":,s,e,t, ,i,c"),
Task("Copy the word under the cursor.", "y,w"),
Task("Replace the text under the cursor with <w1>.", "R,<w1>"),
Task("Insert text at the end of the line.", "A"),
Task("Insert text after the cursor.", "a"),
Task("Insert a new line below the current line.", "o"),
Task("Insert a new line above the current line.", "O"),
Task("Move to the beginning of the document.", "g,g"),
Task("Move to the end of the line.", "$"),
Task("Move to the end of the document.", "G"),
Task(
"Select the next four characters and copy them.", "v,right,right,right,right,y"
),
Task("Switch to the next window.", "C-w,C-w"),
Task("Swap the position of the current window with another.", "C-w,r"),
Task("Copy the current line.", "y,y"),
Task("Copy all content.", "y"),
Task("Paste the copied content.", "p"),
Task("Replace the character under the cursor with '<randc1>'.", "r,<randc1>"),
Task("Delete the character under the cursor.", "x"),
Task("Delete the line under the cursor.", "d,d"),
Task("Cut the current line.", "c,c"),
Task("Type <w1>.", "<w1>"),
]
# shift select Move with>>
def main():
questions_correct = []
questions_incorrect = []
question_count = 0
durations = []
while tasks:
clear_terminal()
if not durations:
avg_reaction_time = 0
else:
avg_reaction_time = sum(durations) / len(durations)
num_correct = len(questions_correct)
num_incorrect = len(questions_incorrect)
avg_time = round(sum(durations) / len(durations), 2) if durations else 0
print(
"Correct: {}\tIncorrect: {}\tAvg reaction time: {}".format(
num_correct, num_incorrect, avg_time
)
)
print("")
question_count += 1
task = random.choice(tasks)
print("{}. ".format(question_count), end="")
time_start = time.time()
if task.execute():
tasks.remove(task)
questions_correct.append(task)
else:
questions_incorrect.append(task)
time_end = time.time()
durations.append(time_end - time_start)
if __name__ == "__main__":
main()