stunning-train 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: stunning-train
3
+ Version: 0.1.0
4
+ Summary: Terminal-based Fast Screen Reader
5
+ Classifier: Programming Language :: Python :: 3
6
+ Requires-Python: >=3.7
@@ -0,0 +1 @@
1
+ # stunning-train
@@ -0,0 +1,19 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "stunning-train"
7
+ version = "0.1.0"
8
+ description = "Terminal-based Fast Screen Reader"
9
+ requires-python = ">=3.7"
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3",
12
+ ]
13
+ dependencies = []
14
+
15
+ [project.scripts]
16
+ stt = "stunning_train.cli:run"
17
+
18
+ [tool.setuptools.packages.find]
19
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env python3
2
+ import curses
3
+ import time
4
+ import os
5
+ import argparse
6
+ try:
7
+ from stunning_train.core import reader
8
+ except ImportError:
9
+ from core import reader
10
+
11
+ def choose_file(stdscr):
12
+ all_items = os.listdir('.')
13
+ files = []
14
+ for f in all_items:
15
+ if os.path.isfile(f):
16
+ files.append(f)
17
+ if len(files) == 0:
18
+ return None
19
+ selected = 0
20
+ num_files = len(files)
21
+ while True:
22
+ stdscr.clear()
23
+ max_y, max_x = stdscr.getmaxyx()
24
+ start_y = (max_y - num_files) // 2
25
+ if start_y < 0:
26
+ start_y = 0
27
+ for idx in range(num_files):
28
+ filename = files[idx]
29
+ if idx == selected:
30
+ prefix = "> "
31
+ else:
32
+ prefix = " "
33
+ line = prefix + filename
34
+ line_len = len(line)
35
+ diff_x = max_x - line_len
36
+ x = diff_x // 2
37
+ if x < 0:
38
+ x = 0
39
+ y = start_y + idx
40
+ stdscr.addstr(y, x, line)
41
+
42
+ stdscr.refresh()
43
+ key = stdscr.getch()
44
+ if key == curses.KEY_UP:
45
+ selected = selected - 1
46
+ if selected < 0:
47
+ selected = num_files - 1
48
+ elif key == curses.KEY_DOWN:
49
+ selected = selected + 1
50
+ if selected >= num_files:
51
+ selected = 0
52
+ elif key == 10 or key == 13:
53
+ chosen_file = files[selected]
54
+ return chosen_file
55
+
56
+ def main(stdscr, args):
57
+ curses.curs_set(0)
58
+ stdscr.keypad(True)
59
+ text = None
60
+ if args.string is not None:
61
+ text = args.string
62
+ elif args.file is not None:
63
+ f = open(args.file, 'r')
64
+ text = f.read()
65
+ f.close()
66
+ else:
67
+ filename = choose_file(stdscr)
68
+ if filename is None:
69
+ return
70
+ f = open(filename, 'r')
71
+ text = f.read()
72
+ f.close()
73
+ r = reader(text, wpm=args.wpm)
74
+ while r.has_next() == True or r.current is not None:
75
+ if r.current is None:
76
+ r.next_word()
77
+ stdscr.clear()
78
+ word = r.current
79
+ history_list, current_word, lookahead_list = r.nearby_words()
80
+ history_str = ""
81
+ for h_word in history_list:
82
+ history_str = history_str + h_word + " "
83
+ lookahead_str = ""
84
+ for l_word in lookahead_list:
85
+ lookahead_str = lookahead_str + " " + l_word
86
+ max_y, max_x = stdscr.getmaxyx()
87
+ y = max_y // 2
88
+ word_len = len(word)
89
+ diff_x = max_x - word_len
90
+ x = diff_x // 2
91
+ if x < 0:
92
+ x = 0
93
+ hx = x - len(history_str)
94
+ if hx < 0:
95
+ slice_start = len(history_str) - x
96
+ history_str = history_str[slice_start:]
97
+ hx = 0
98
+ lx = x + word_len
99
+ if lx < max_x:
100
+ space_left = max_x - lx
101
+ lookahead_str = lookahead_str[:space_left]
102
+ if len(history_str) > 0:
103
+ stdscr.addstr(y, hx, history_str, curses.A_DIM)
104
+ stdscr.addstr(y, x, word)
105
+ if lx < max_x:
106
+ if len(lookahead_str) > 0:
107
+ stdscr.addstr(y, lx, lookahead_str, curses.A_DIM)
108
+ pct = r.words_read / r.size
109
+ if pct > 1.0:
110
+ pct = 1.0
111
+ bar_width = 20
112
+ filled = int(pct * bar_width)
113
+ empty = bar_width - filled
114
+ bar_str = "["
115
+ for _ in range(filled):
116
+ bar_str = bar_str + "-"
117
+ for _ in range(empty):
118
+ bar_str = bar_str + " "
119
+ bar_str = bar_str + "]"
120
+ percent_num = int(pct * 100)
121
+ percent_str = " " + str(percent_num) + "%"
122
+ full_str = bar_str + percent_str
123
+ bar_len = len(full_str)
124
+ bar_x = (max_x - bar_len) // 2
125
+ if bar_x < 0:
126
+ bar_x = 0
127
+ bar_y = max_y - 2
128
+ if bar_y > y:
129
+ stdscr.addstr(bar_y, bar_x, full_str)
130
+ stdscr.refresh()
131
+ delay_ms = int(r.get_delay() * 1000)
132
+ stdscr.timeout(delay_ms)
133
+ key = stdscr.getch()
134
+ if key == curses.KEY_RIGHT:
135
+ steps = int(r.size * 0.02)
136
+ if steps < 1:
137
+ steps = 1
138
+ r.skip_forward(steps)
139
+ elif key == curses.KEY_LEFT:
140
+ steps = int(r.size * 0.02)
141
+ if steps < 1:
142
+ steps = 1
143
+ for _ in range(steps):
144
+ r.go_backward()
145
+ else:
146
+ if r.has_next() == True:
147
+ r.next_word()
148
+ else:
149
+ break
150
+
151
+ def run():
152
+ parser = argparse.ArgumentParser(description="Terminal-based Fast Screen Reader ")
153
+ parser.add_argument('-f', '--file', type=str, help="File Path(needed if file is outside the cwd)")
154
+ parser.add_argument('-s', '--string', type=str, help="Input String")
155
+ parser.add_argument('-w', '--wpm', type=int, default=300, help="SET WPM(default: 300)")
156
+ args = parser.parse_args()
157
+ curses.wrapper(main, args)
158
+
159
+ if __name__ == "__main__":
160
+ run()
@@ -0,0 +1,81 @@
1
+ import io
2
+ class reader:
3
+ def file_stream_gen(self,obj):
4
+ for line in obj:
5
+ for word in line.split():
6
+ yield word
7
+ def __init__(self, stream, wpm=300, chunk_size= 5):
8
+ self.wpm= wpm
9
+ self.chunk_size = chunk_size
10
+ if isinstance(stream, str):
11
+ self.stream=iter(stream.split())
12
+ self.size= len(stream.split())
13
+ elif isinstance(stream, io.IOBase):
14
+ curr = stream.tell()
15
+ stream.seek(0, 2)
16
+ self.size = stream.tell()
17
+ stream.seek(curr)
18
+ self.stream = self.file_stream_gen(stream)
19
+ else:
20
+ raise TypeError("Stream must be a string or a file-like object")
21
+ self.history = []
22
+ self.lookahead = []
23
+ self.current = None
24
+ self.words_read = 0
25
+ self.fill_lookahead()
26
+ def fill_lookahead(self):
27
+ while len(self.lookahead) < self.chunk_size:
28
+ try:
29
+ word = next(self.stream)
30
+ self.lookahead.append(word)
31
+ except StopIteration:
32
+ break
33
+
34
+ def get_speed(self):
35
+ return self.wpm
36
+
37
+ def set_speed(self, value):
38
+ if value <= 0:
39
+ raise ValueError("Speed must be greater than 0")
40
+ self.wpm = value
41
+
42
+ def get_delay(self):
43
+ return 60.0 / self.wpm
44
+
45
+
46
+ def has_next(self):
47
+ self.fill_lookahead()
48
+ return len(self.lookahead) > 0
49
+
50
+ def next_word(self):
51
+ if not self.has_next():
52
+ raise StopIteration()
53
+ if self.current is not None:
54
+ self.history.append(self.current)
55
+ if len(self.history) > self.chunk_size:
56
+ self.history.pop(0)
57
+ self.current = self.lookahead.pop(0)
58
+ self.words_read = self.words_read + 1
59
+ self.fill_lookahead()
60
+ return self.current
61
+
62
+ def skip_forward(self, n=1):
63
+ for _ in range(n):
64
+ if not self.has_next():
65
+ break
66
+ self.next_word()
67
+ return self.current
68
+
69
+ def go_backward(self):
70
+ if len(self.history) == 0:
71
+ return self.current
72
+ if self.current is not None:
73
+ self.lookahead.insert(0, self.current)
74
+ self.current = self.history.pop()
75
+ self.words_read = self.words_read - 1
76
+ if self.words_read < 0:
77
+ self.words_read = 0
78
+ return self.current
79
+
80
+ def nearby_words(self):
81
+ return self.history.copy(), self.current, self.lookahead.copy()
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: stunning-train
3
+ Version: 0.1.0
4
+ Summary: Terminal-based Fast Screen Reader
5
+ Classifier: Programming Language :: Python :: 3
6
+ Requires-Python: >=3.7
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/stunning_train/__init__.py
4
+ src/stunning_train/cli.py
5
+ src/stunning_train/core.py
6
+ src/stunning_train.egg-info/PKG-INFO
7
+ src/stunning_train.egg-info/SOURCES.txt
8
+ src/stunning_train.egg-info/dependency_links.txt
9
+ src/stunning_train.egg-info/entry_points.txt
10
+ src/stunning_train.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ stt = stunning_train.cli:run
@@ -0,0 +1 @@
1
+ stunning_train