various
This commit is contained in:
parent
2e14654474
commit
b11bbf9599
|
@ -0,0 +1,283 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# speedread: A simple terminal-based open source spritz-alike
|
||||
#
|
||||
# Show input text as a per-word RSVP (rapid serial visual presentation)
|
||||
# aligned on optimal reading points. This kind of input mode allows
|
||||
# reading text at a much more rapid pace than usual as the eye can
|
||||
# stay fixed on a single place.
|
||||
#
|
||||
# (c) Petr Baudis <pasky@ucw.cz> 2014
|
||||
# MIT licence
|
||||
#
|
||||
# Usage: cat file.txt | speedread [-w WORDSPERMINUTE] [-r RESUMEPOINT] [-m]
|
||||
#
|
||||
# The default of 250 words per minut is very timid, designed so that
|
||||
# you get used to this. Be sure to try cranking this up, 500wpm
|
||||
# should still be fairly easy to follow even for beginners.
|
||||
#
|
||||
# speedread can join short words together if you specify the -m switch.
|
||||
# It did not work well for pasky so far, though.
|
||||
#
|
||||
# speedread is slightly interactive, with these controls accepted:
|
||||
#
|
||||
# [ - slow down by 10%
|
||||
# ] - speed up by 10%
|
||||
# space - pause (and show the last two lines)
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use autodie;
|
||||
use v5.14;
|
||||
|
||||
my $wpm = 250;
|
||||
my $resume = 0;
|
||||
my $multiword = 0;
|
||||
|
||||
|
||||
use utf8;
|
||||
binmode(STDIN, ":encoding(UTF-8)");
|
||||
binmode(STDOUT, ":encoding(UTF-8)");
|
||||
|
||||
use Term::ANSIColor;
|
||||
use POSIX qw(ceil floor);
|
||||
use Time::HiRes qw(time sleep gettimeofday tv_interval);
|
||||
|
||||
use Getopt::Long;
|
||||
GetOptions("wpm|w=i" => \$wpm,
|
||||
"resume|r=i" => \$resume,
|
||||
"multiword|m" => \$multiword);
|
||||
|
||||
my $wordtime = 0.9; # relative to wpm
|
||||
my $lentime = 0.04; # * sqrt(length $word), relative to wpm
|
||||
my $commatime = 2; # relative to wpm
|
||||
my $fstoptime = 3; # relative to wpm
|
||||
my $multitime = 1.2; # relative to wpm
|
||||
my $firsttime = 0.2; # [s]
|
||||
my $ORPloc = 0.35;
|
||||
my $ORPmax = 0.2;
|
||||
my $ORPvisualpos = 20;
|
||||
my $cursorpos = 64;
|
||||
my $paused = 0;
|
||||
my $current_word;
|
||||
my $current_orp;
|
||||
my $next_word_time = 0;
|
||||
my $next_input_time = 0;
|
||||
my $skipped = 0;
|
||||
|
||||
my @lastlines;
|
||||
my $tty = rawinput->new();
|
||||
$| = 1;
|
||||
|
||||
my $wordcounter = 0;
|
||||
my $lettercounter = 0;
|
||||
my $t0 = [gettimeofday];
|
||||
sub print_stats {
|
||||
my $elapsed = tv_interval($t0, [gettimeofday]);
|
||||
my $truewpm = $wordcounter / $elapsed * 60;
|
||||
printf("\n %.2fs, %d words, %d letters, %s%.2f%s true wpm\n",
|
||||
$elapsed, $wordcounter, $lettercounter,
|
||||
color('bold green'), $truewpm, color('reset'));
|
||||
}
|
||||
$SIG{INT} = sub {
|
||||
print_stats;
|
||||
my $resume_word = $wordcounter + $resume;
|
||||
say " To resume from this point run with argument -r $resume_word";
|
||||
exit;
|
||||
};
|
||||
|
||||
main();
|
||||
|
||||
# ORP: Optical Recognition Point (the red-colored alignment pilot),
|
||||
# the way Spritz probably does it.
|
||||
sub find_ORP {
|
||||
my ($word, $ORPloc) = @_;
|
||||
|
||||
return 4 if (length($word) > 13);
|
||||
return (0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3)[length($word)];
|
||||
}
|
||||
|
||||
sub show_guide {
|
||||
# Top visual guide
|
||||
say(" "x$ORPvisualpos . color('red') . "v" . color('reset') . "\033[K");
|
||||
}
|
||||
|
||||
sub show_word {
|
||||
my ($word, $i) = @_;
|
||||
|
||||
my $pivotch = substr($word, $i, 1);
|
||||
$pivotch = "·" if $pivotch eq ' ';
|
||||
|
||||
print("\r\033[K"
|
||||
. " " x ($ORPvisualpos - $i)
|
||||
. color("bold")
|
||||
. substr($word, 0, $i)
|
||||
. color("red")
|
||||
. $pivotch
|
||||
. color("reset")
|
||||
. color("bold")
|
||||
. substr($word, $i+1)
|
||||
. color("reset")
|
||||
. " " x ($cursorpos - (($ORPvisualpos - $i) + length($word)))
|
||||
. "$wpm wpm"
|
||||
. ($paused ? " ".color("yellow")."PAUSED".color("reset") : ""));
|
||||
}
|
||||
|
||||
sub word_time {
|
||||
my ($word) = @_;
|
||||
|
||||
my $time = $wordtime;
|
||||
if ($word =~ /[\.\?]\W*$/) {
|
||||
$time = $fstoptime;
|
||||
} elsif ($word =~ /[:;,]\W*$/) {
|
||||
$time = $commatime;
|
||||
} elsif ($word =~ / /) {
|
||||
$time = $multitime;
|
||||
}
|
||||
$time += sqrt(length($word)) * $lentime;
|
||||
$time *= 60 / $wpm;
|
||||
|
||||
# Give user some time to focus on the first word, even with high wpm.
|
||||
$time = $firsttime if ($wordcounter == 0 and $time < $firsttime);
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
sub print_context {
|
||||
my ($wn) = @_;
|
||||
# One line up and to its beginning
|
||||
print "\r\033[K\033[A\033[K";
|
||||
# First line of context
|
||||
say $lastlines[1] if $lastlines[1];
|
||||
# In second line of context, highlight our word
|
||||
my $line0 = $lastlines[0];
|
||||
my $c0 = color('yellow');
|
||||
my $c1 = color('reset');
|
||||
$line0 =~ s/^((?:.*?(?:-|\s)+){$wn})(.*?)(-|\s)/$1$c0$2$c1$3/;
|
||||
say $line0;
|
||||
}
|
||||
|
||||
sub process_keys {
|
||||
my ($word, $i, $wn) = @_;
|
||||
while ($tty->key_pressed()) {
|
||||
my $ch = $tty->getch();
|
||||
if ($ch eq '[') {
|
||||
$wpm = int($wpm * 0.9);
|
||||
|
||||
} elsif ($ch eq ']') {
|
||||
$wpm = int($wpm * 1.1);
|
||||
|
||||
} elsif ($ch eq ' ') {
|
||||
$paused = not $paused;
|
||||
if ($paused) {
|
||||
# Print context.
|
||||
print_context($wn);
|
||||
show_guide();
|
||||
show_word($word, $i);
|
||||
}
|
||||
else {
|
||||
$next_word_time = time();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub main {
|
||||
show_guide();
|
||||
|
||||
$next_word_time = time();
|
||||
$next_input_time = time();
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
|
||||
unshift @lastlines, $_;
|
||||
pop @lastlines if @lastlines > 2;
|
||||
|
||||
my (@words) = grep { /./ } split /(?:-|\s)+/;
|
||||
|
||||
if ($multiword) {
|
||||
# Join adjecent short words
|
||||
for (my $i = 0; $i < $#words - 1; $i++) {
|
||||
if (length($words[$i]) <= 3 and length($words[$i+1]) <= 3) {
|
||||
$words[$i] .= ' ' . $words[$i+1];
|
||||
splice(@words, $i+1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $wn = 0;
|
||||
while (scalar(@words) > 0) {
|
||||
if ($skipped < $resume) {
|
||||
$skipped++;
|
||||
shift @words;
|
||||
next;
|
||||
}
|
||||
|
||||
my $current_time = time();
|
||||
|
||||
if ($next_word_time <= $current_time and !$paused) {
|
||||
$current_word = shift @words;
|
||||
$current_orp = find_ORP($current_word, $ORPloc);
|
||||
$next_word_time += word_time($current_word);
|
||||
$wordcounter++;
|
||||
$lettercounter += length($current_word);
|
||||
$wn++;
|
||||
}
|
||||
|
||||
if ($next_input_time <= $current_time) {
|
||||
process_keys($current_word, $current_orp, $wn);
|
||||
$next_input_time += 0.05; # checking for input 20 times / second seems to give a reasonably responsive UI
|
||||
}
|
||||
|
||||
# redrawing the word on each "frame" gives a more responsive UI
|
||||
# (we don't have to wait for the word to change to display changed stats like wpm)
|
||||
show_word($current_word, $current_orp);
|
||||
|
||||
my $sleep_time = ($next_word_time < $next_input_time and !$paused) ? $next_word_time-$current_time : $next_input_time-$current_time;
|
||||
sleep($sleep_time) if ($sleep_time > 0);
|
||||
}
|
||||
}
|
||||
|
||||
print_stats();
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
package rawinput;
|
||||
|
||||
# An ad-hoc interface to interactive terminal input. Term::Screen *should*
|
||||
# have been a natural choice here, unfortunately it is fixated at reading
|
||||
# from stdin instead of /dev/tty. Tough.
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $self;
|
||||
open $self, '/dev/tty';
|
||||
bless $self, $class;
|
||||
stty('min 1', '-icanon', '-echo');
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
stty('cooked', 'echo');
|
||||
}
|
||||
|
||||
sub stty {
|
||||
my $self = shift;
|
||||
eval { system('stty', $^O eq 'darwin' ? '-f' : '-F', '/dev/tty', @_); };
|
||||
}
|
||||
|
||||
sub key_pressed {
|
||||
my $self = shift;
|
||||
my $readfields = '';
|
||||
vec($readfields, fileno($self), 1) = 1;
|
||||
my $ready = 0;
|
||||
eval { $ready = select($readfields, undef, undef, 0); };
|
||||
return $ready;
|
||||
}
|
||||
|
||||
sub getch {
|
||||
my $self = shift;
|
||||
getc($self);
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -132,10 +132,10 @@
|
|||
id="rect"
|
||||
style="fill:blue;"
|
||||
usecurrent="1"
|
||||
width="7.97975"
|
||||
height="141.497"
|
||||
width="120.208"
|
||||
height="33.335"
|
||||
rx="0"
|
||||
ry="3.25" />
|
||||
ry="1.18252" />
|
||||
<eventcontext
|
||||
id="3dbox"
|
||||
style="stroke:none;stroke-linejoin:round;"
|
||||
|
@ -171,16 +171,17 @@
|
|||
end="0"
|
||||
start="0"
|
||||
usecurrent="1"
|
||||
rx="131.32"
|
||||
ry="131.32" />
|
||||
rx="48.1646"
|
||||
ry="48.1646" />
|
||||
<eventcontext
|
||||
id="star"
|
||||
magnitude="5"
|
||||
magnitude="6"
|
||||
style="fill:yellow;"
|
||||
usecurrent="1"
|
||||
proportion="0.5"
|
||||
rounded="0"
|
||||
randomized="0" />
|
||||
randomized="0"
|
||||
isflatsided="1" />
|
||||
<eventcontext
|
||||
id="spiral"
|
||||
style="fill:none;stroke:black"
|
||||
|
@ -335,10 +336,11 @@
|
|||
font_sample="AaBbCcIiPpQq12369$€¢?.;/()"
|
||||
show_sample_in_list="1"
|
||||
style="fill:black;fill-opacity:1;stroke:none;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;letter-spacing:0px;word-spacing:0px"
|
||||
selcue="1">
|
||||
selcue="1"
|
||||
align_mode="1">
|
||||
<group
|
||||
id="lineheight"
|
||||
display_unit="0" />
|
||||
display_unit="0"
|
||||
id="lineheight" />
|
||||
</eventcontext>
|
||||
<eventcontext
|
||||
id="nodes"
|
||||
|
@ -424,12 +426,12 @@
|
|||
offset="0"
|
||||
offsetunits="cm" />
|
||||
<group
|
||||
id="measure"
|
||||
fontsize="10"
|
||||
precision="2"
|
||||
scale="100"
|
||||
unit="px"
|
||||
offset="5"
|
||||
unit="px" />
|
||||
scale="100"
|
||||
precision="2"
|
||||
fontsize="10"
|
||||
id="measure" />
|
||||
</group>
|
||||
<group
|
||||
id="palette">
|
||||
|
@ -576,15 +578,27 @@
|
|||
page="0"
|
||||
x="0"
|
||||
y="0"
|
||||
w="354"
|
||||
h="427"
|
||||
w="451"
|
||||
h="485"
|
||||
visible="1"
|
||||
state="2"
|
||||
placement="1" />
|
||||
placement="5" />
|
||||
<group
|
||||
id="filtereffects" />
|
||||
<group
|
||||
id="textandfont" />
|
||||
id="textandfont"
|
||||
panel_size="1"
|
||||
panel_ratio="100"
|
||||
panel_mode="1"
|
||||
panel_wrap="0"
|
||||
panel_border="0"
|
||||
x="0"
|
||||
y="0"
|
||||
w="451"
|
||||
h="485"
|
||||
visible="1"
|
||||
state="2"
|
||||
placement="5" />
|
||||
<group
|
||||
id="transformation"
|
||||
applyseparately="0" />
|
||||
|
@ -595,14 +609,14 @@
|
|||
panel_mode="1"
|
||||
panel_wrap="0"
|
||||
panel_border="0"
|
||||
align-to="0"
|
||||
align-to="4"
|
||||
x="0"
|
||||
y="0"
|
||||
w="354"
|
||||
h="412"
|
||||
w="451"
|
||||
h="485"
|
||||
visible="1"
|
||||
state="2"
|
||||
placement="2" />
|
||||
placement="5" />
|
||||
<group
|
||||
id="xml" />
|
||||
<group
|
||||
|
@ -621,8 +635,8 @@
|
|||
panel_mode="1"
|
||||
panel_wrap="0"
|
||||
panel_border="0"
|
||||
x="950"
|
||||
y="210"
|
||||
x="821"
|
||||
y="466"
|
||||
w="623"
|
||||
h="652"
|
||||
visible="0"
|
||||
|
@ -656,17 +670,17 @@
|
|||
panel_border="0"
|
||||
x="0"
|
||||
y="0"
|
||||
w="356"
|
||||
h="487"
|
||||
w="451"
|
||||
h="485"
|
||||
visible="1"
|
||||
state="2"
|
||||
placement="2">
|
||||
placement="5">
|
||||
<group
|
||||
id="exportarea"
|
||||
value="page" />
|
||||
value="drawing" />
|
||||
<group
|
||||
id="defaultxdpi"
|
||||
value="128.21" />
|
||||
value="304.76" />
|
||||
</group>
|
||||
<group
|
||||
id="save_as"
|
||||
|
@ -688,7 +702,7 @@
|
|||
<group
|
||||
id="import"
|
||||
enable_preview="1"
|
||||
path="/home/amolith/repos/nixnet/assets/svgs/"
|
||||
path="/home/amolith/Pictures/Me/Web/"
|
||||
ask="1"
|
||||
link="embed"
|
||||
scale="optimizeQuality"
|
||||
|
@ -728,7 +742,7 @@
|
|||
panel_mode="1"
|
||||
panel_wrap="0"
|
||||
panel_border="0"
|
||||
x="663"
|
||||
x="623"
|
||||
y="0"
|
||||
w="585"
|
||||
h="398"
|
||||
|
@ -747,6 +761,20 @@
|
|||
on-focus="1.0"
|
||||
on-blur="0.50"
|
||||
animate-time="100" />
|
||||
<group
|
||||
id="symbols"
|
||||
panel_size="1"
|
||||
panel_ratio="100"
|
||||
panel_mode="1"
|
||||
panel_wrap="0"
|
||||
panel_border="0"
|
||||
x="0"
|
||||
y="0"
|
||||
w="451"
|
||||
h="485"
|
||||
visible="1"
|
||||
state="2"
|
||||
placement="5" />
|
||||
</group>
|
||||
<group
|
||||
id="printing">
|
||||
|
@ -1035,14 +1063,15 @@
|
|||
</group>
|
||||
<group
|
||||
id="extensions"
|
||||
org.inkscape.input.gdkpixbuf.png.scale="optimizeQuality" />
|
||||
org.inkscape.input.gdkpixbuf.png.scale="optimizeQuality"
|
||||
org.inkscape.input.gdkpixbuf.jpg.scale="optimizeQuality" />
|
||||
<group
|
||||
id="desktop"
|
||||
style="line-height:1.25;fill:#ffffff;fill-opacity:1;-inkscape-font-specification:'Open Sans';font-family:'Open Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">
|
||||
style="line-height:1.25;fill:#ffffff;fill-opacity:1;-inkscape-font-specification:Comfortaa;font-family:Comfortaa;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:16.11599986px;text-anchor:middle;text-align:center;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;stroke:none;stroke-opacity:1;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none">
|
||||
<group
|
||||
width="663"
|
||||
width="1336"
|
||||
height="698"
|
||||
x="688"
|
||||
x="15"
|
||||
y="35"
|
||||
fullscreen="0"
|
||||
id="geometry"
|
||||
|
|
|
@ -1 +1 @@
|
|||
756
|
||||
1103
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
sw_volume: 64
|
||||
audio_device_state:1:pulse audio
|
||||
audio_device_state:1:my_fifo
|
||||
state: play
|
||||
current: 830
|
||||
time: 3.858000
|
||||
state: pause
|
||||
current: 713
|
||||
time: 332.959000
|
||||
random: 0
|
||||
repeat: 0
|
||||
single: 0
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2,4 +2,4 @@ set-option -g prefix C-q
|
|||
set-window-option -g mode-keys vi
|
||||
bind-key -t vi-copy 'v' begin-selection
|
||||
bind-key -t vi-copy 'y' copy-selection
|
||||
set -g mouse on
|
||||
set -g mouse off
|
||||
|
|
|
@ -10,6 +10,7 @@ export PATH="$HOME/.cargo/bin:$PATH"
|
|||
export PATH="$PATH:$HOME/.local/bin"
|
||||
export PATH="$HOME/.gem/ruby/2.6.0/bin:$PATH"
|
||||
export PATH="$HOME/.rbenv/bin:$PATH"
|
||||
export PATH="$HOME/go/bin:$PATH"
|
||||
export GEM_HOME="$HOME/gems"
|
||||
export CHROOT="$HOME/chroot"
|
||||
export EDITOR="nvim"
|
||||
|
@ -57,6 +58,7 @@ alias b="bluetoothctl"
|
|||
alias vim="nvim"
|
||||
alias v="nvim"
|
||||
alias ssh="ssh -Y"
|
||||
alias gen="pwgen -s 20 1 | xclip -selection clipboard"
|
||||
unset zle_bracketed_paste
|
||||
|
||||
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||
|
|
Loading…
Reference in New Issue