8 changed files with 2147 additions and 0 deletions
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash |
||||
|
||||
VOL=`mpc volume | sed '1 s/volume://'` |
||||
PERC=`echo $VOL` |
||||
VOLBAR=`echo -e "$PERC" | dzen2-gdbar -bg '#454545' -fg '#cd546c' -h 1 -w 50 | sed "s/\ .*\%//g"` |
||||
|
||||
echo "$VOLBAR" |
||||
|
@ -0,0 +1,369 @@
@@ -0,0 +1,369 @@
|
||||
#!/usr/bin/env python2 |
||||
''' |
||||
python/curses epub reader. Requires BeautifulSoup |
||||
|
||||
Keyboard commands: |
||||
Esc/q - quit |
||||
Tab/Left/Right - toggle between TOC and chapter views |
||||
TOC view: |
||||
Up - up a line |
||||
Down - down a line |
||||
PgUp - up a page |
||||
PgDown - down a page |
||||
Chapter view: |
||||
Up - up a page |
||||
Down - down a page |
||||
PgUp - up a line |
||||
PgDown - down a line |
||||
i - open images on page in web browser |
||||
''' |
||||
|
||||
import curses.wrapper, curses.ascii |
||||
import formatter, htmllib, locale, os, StringIO, re, readline, tempfile, zipfile |
||||
import base64, webbrowser |
||||
|
||||
from BeautifulSoup import BeautifulSoup |
||||
|
||||
try: |
||||
from fabulous import image |
||||
import PIL |
||||
except ImportError: |
||||
images = False |
||||
else: |
||||
images = True |
||||
|
||||
locale.setlocale(locale.LC_ALL, 'en_US.utf-8') |
||||
|
||||
basedir = '' |
||||
|
||||
def run(screen, program, *args): |
||||
curses.nocbreak() |
||||
screen.keypad(0) |
||||
curses.echo() |
||||
pid = os.fork() |
||||
if not pid: |
||||
os.execvp(program, (program,) + args) |
||||
os.wait()[0] |
||||
curses.noecho() |
||||
screen.keypad(1) |
||||
curses.cbreak() |
||||
|
||||
def open_image(screen, name, s): |
||||
''' show images with PIL and fabulous ''' |
||||
if not images: |
||||
screen.addstr(0, 0, "missing PIL or fabulous", curses.A_REVERSE) |
||||
return |
||||
|
||||
ext = os.path.splitext(name)[1] |
||||
|
||||
screen.erase() |
||||
screen.refresh() |
||||
curses.setsyx(0, 0) |
||||
image_file = tempfile.NamedTemporaryFile(suffix=ext, delete=False) |
||||
image_file.write(s) |
||||
image_file.close() |
||||
try: |
||||
print image.Image(image_file.name) |
||||
except: |
||||
print image_file.name |
||||
finally: |
||||
os.unlink(image_file.name) |
||||
|
||||
def textify(html_snippet, img_size=(80, 45), maxcol=72): |
||||
''' text dump of html ''' |
||||
class Parser(htmllib.HTMLParser): |
||||
def anchor_end(self): |
||||
self.anchor = None |
||||
def handle_image(self, source, alt, ismap, alight, width, height): |
||||
global basedir |
||||
self.handle_data( |
||||
'[img="{0}{1}" "{2}"]'.format(basedir, source, alt) |
||||
) |
||||
|
||||
class Formatter(formatter.AbstractFormatter): |
||||
pass |
||||
|
||||
class Writer(formatter.DumbWriter): |
||||
def __init__(self, fl, maxcol=72): |
||||
formatter.DumbWriter.__init__(self, fl) |
||||
self.maxcol = maxcol |
||||
def send_label_data(self, data): |
||||
self.send_flowing_data(data) |
||||
self.send_flowing_data(' ') |
||||
|
||||
o = StringIO.StringIO() |
||||
p = Parser(Formatter(Writer(o, maxcol))) |
||||
p.feed(html_snippet) |
||||
p.close() |
||||
|
||||
return o.getvalue() |
||||
|
||||
def table_of_contents(fl): |
||||
global basedir |
||||
|
||||
# find opf file |
||||
soup = BeautifulSoup(fl.read('META-INF/container.xml')) |
||||
opf = dict(soup.find('rootfile').attrs)['full-path'] |
||||
|
||||
basedir = os.path.dirname(opf) |
||||
if basedir: |
||||
basedir = '{0}/'.format(basedir) |
||||
|
||||
soup = BeautifulSoup(fl.read(opf)) |
||||
|
||||
# title |
||||
yield (soup.find('dc:title').text, None) |
||||
|
||||
# all files, not in order |
||||
x, ncx = {}, None |
||||
for item in soup.find('manifest').findAll('item'): |
||||
d = dict(item.attrs) |
||||
x[d['id']] = '{0}{1}'.format(basedir, d['href']) |
||||
if d['media-type'] == 'application/x-dtbncx+xml': |
||||
ncx = '{0}{1}'.format(basedir, d['href']) |
||||
|
||||
# reading order, not all files |
||||
y = [] |
||||
for item in soup.find('spine').findAll('itemref'): |
||||
y.append(x[dict(item.attrs)['idref']]) |
||||
|
||||
z = {} |
||||
if ncx: |
||||
# get titles from the toc |
||||
soup = BeautifulSoup(fl.read(ncx)) |
||||
|
||||
for navpoint in soup('navpoint'): |
||||
k = navpoint.content.get('src', None) |
||||
# strip off any anchor text |
||||
k = k.split('#')[0] |
||||
if k: |
||||
z[k] = navpoint.navlabel.text |
||||
|
||||
# output |
||||
for section in y: |
||||
if section in z: |
||||
yield (z[section].encode('utf-8'), section.encode('utf-8')) |
||||
else: |
||||
yield (u'', section.encode('utf-8').strip()) |
||||
|
||||
def list_chaps(screen, chaps, start, length): |
||||
for i, (title, src) in enumerate(chaps[start:start+length]): |
||||
try: |
||||
if start == 0: |
||||
screen.addstr(i, 0, ' {0}'.format(title), curses.A_BOLD) |
||||
else: |
||||
screen.addstr(i, 0, '{0:-5} {1}'.format(start, title)) |
||||
except: |
||||
pass |
||||
start += 1 |
||||
screen.refresh() |
||||
return i |
||||
|
||||
def check_epub(fl): |
||||
if os.path.isfile(fl) and os.path.splitext(fl)[1].lower() == '.epub': |
||||
return True |
||||
|
||||
def dump_epub(fl, maxcol=float("+inf")): |
||||
if not check_epub(fl): |
||||
return |
||||
fl = zipfile.ZipFile(fl, 'r') |
||||
chaps = [i for i in table_of_contents(fl)] |
||||
for title, src in chaps: |
||||
print title |
||||
print '-' * len(title) |
||||
if src: |
||||
soup = BeautifulSoup(fl.read(src)) |
||||
print textify( |
||||
unicode(soup.find('body')).encode('utf-8'), |
||||
maxcol=maxcol, |
||||
) |
||||
print '\n' |
||||
|
||||
def curses_epub(screen, fl): |
||||
if not check_epub(fl): |
||||
return |
||||
|
||||
#curses.mousemask(curses.BUTTON1_CLICKED) |
||||
|
||||
fl = zipfile.ZipFile(fl, 'r') |
||||
chaps = [i for i in table_of_contents(fl)] |
||||
chaps_pos = [0 for i in chaps] |
||||
start = 0 |
||||
cursor_row = 0 |
||||
|
||||
# toc |
||||
while True: |
||||
curses.curs_set(1) |
||||
maxy, maxx = screen.getmaxyx() |
||||
|
||||
if cursor_row >= maxy: |
||||
cursor_row = maxy - 1 |
||||
|
||||
len_chaps = list_chaps(screen, chaps, start, maxy) |
||||
screen.move(cursor_row, 0) |
||||
ch = screen.getch() |
||||
|
||||
# quit |
||||
if ch == curses.ascii.ESC: |
||||
return |
||||
try: |
||||
if chr(ch) == 'q': |
||||
return |
||||
except: |
||||
pass |
||||
|
||||
# up/down line |
||||
if ch in [curses.KEY_DOWN]: |
||||
if start < len(chaps) - maxy: |
||||
start += 1 |
||||
screen.clear() |
||||
elif cursor_row < maxy - 1 and cursor_row < len_chaps: |
||||
cursor_row += 1 |
||||
elif ch in [curses.KEY_UP]: |
||||
if start > 0: |
||||
start -= 1 |
||||
screen.clear() |
||||
elif cursor_row > 0: |
||||
cursor_row -= 1 |
||||
|
||||
# up/down page |
||||
elif ch in [curses.KEY_NPAGE]: |
||||
if start + maxy - 1 < len(chaps): |
||||
start += maxy - 1 |
||||
if len_chaps < maxy: |
||||
start = len(chaps) - maxy |
||||
screen.clear() |
||||
elif ch in [curses.KEY_PPAGE]: |
||||
if start > 0: |
||||
start -= maxy - 1 |
||||
if start < 0: |
||||
start = 0 |
||||
screen.clear() |
||||
|
||||
# to chapter |
||||
elif ch in [curses.ascii.HT, curses.KEY_RIGHT, curses.KEY_LEFT]: |
||||
if chaps[start + cursor_row][1]: |
||||
html = fl.read(chaps[start + cursor_row][1]) |
||||
soup = BeautifulSoup(html) |
||||
chap = textify( |
||||
unicode(soup.find('body')).encode('utf-8'), |
||||
img_size=screen.getmaxyx(), |
||||
maxcol=screen.getmaxyx()[1] |
||||
).split('\n') |
||||
else: |
||||
chap = '' |
||||
screen.clear() |
||||
curses.curs_set(0) |
||||
|
||||
# chapter |
||||
while True: |
||||
maxy, maxx = screen.getmaxyx() |
||||
images = [] |
||||
for i, line in enumerate(chap[ |
||||
chaps_pos[start + cursor_row]: |
||||
chaps_pos[start + cursor_row] + maxy |
||||
]): |
||||
try: |
||||
screen.addstr(i, 0, line) |
||||
mch = re.search('\[img="([^"]+)" "([^"]*)"\]', line) |
||||
if mch: |
||||
images.append(mch.group(1)) |
||||
except: |
||||
pass |
||||
screen.refresh() |
||||
ch = screen.getch() |
||||
|
||||
# quit |
||||
if ch == curses.ascii.ESC: |
||||
return |
||||
try: |
||||
if chr(ch) == 'q': |
||||
return |
||||
except: |
||||
pass |
||||
|
||||
# to TOC |
||||
if ch in [curses.ascii.HT, curses.KEY_RIGHT, curses.KEY_LEFT]: |
||||
screen.clear() |
||||
break |
||||
|
||||
# up/down page |
||||
elif ch in [curses.KEY_DOWN]: |
||||
if chaps_pos[start + cursor_row] + maxy - 1 < len(chap): |
||||
chaps_pos[start + cursor_row] += maxy - 1 |
||||
screen.clear() |
||||
elif ch in [curses.KEY_UP]: |
||||
if chaps_pos[start + cursor_row] > 0: |
||||
chaps_pos[start + cursor_row] -= maxy - 1 |
||||
if chaps_pos[start + cursor_row] < 0: |
||||
chaps_pos[start + cursor_row] = 0 |
||||
screen.clear() |
||||
|
||||
# up/down line |
||||
elif ch in [curses.KEY_NPAGE]: |
||||
if chaps_pos[start + cursor_row] + maxy - 1 < len(chap): |
||||
chaps_pos[start + cursor_row] += 1 |
||||
screen.clear() |
||||
elif ch in [curses.KEY_PPAGE]: |
||||
if chaps_pos[start + cursor_row] > 0: |
||||
chaps_pos[start + cursor_row] -= 1 |
||||
screen.clear() |
||||
|
||||
#elif ch in [curses.KEY_MOUSE]: |
||||
# id, x, y, z, bstate = curses.getmouse() |
||||
# line = screen.instr(y, 0) |
||||
# mch = re.search('\[img="([^"]+)" "([^"]*)"\]', line) |
||||
# if mch: |
||||
# img_fl = mch.group(1) |
||||
|
||||
else: |
||||
try: |
||||
if chr(ch) == 'i': |
||||
for img in images: |
||||
err = open_image(screen, img, fl.read(img)) |
||||
if err: |
||||
screen.addstr(0, 0, err, curses.A_REVERSE) |
||||
|
||||
# edit html |
||||
elif chr(ch) == 'e': |
||||
|
||||
tmpfl = tempfile.NamedTemporaryFile(delete=False) |
||||
tmpfl.write(html) |
||||
tmpfl.close() |
||||
run(screen, 'vim', tmpfl.name) |
||||
with open(tmpfl.name) as changed: |
||||
new_html = changed.read() |
||||
os.unlink(tmpfl.name) |
||||
if new_html != html: |
||||
pass |
||||
# write to zipfile? |
||||
|
||||
# go back to TOC |
||||
screen.clear() |
||||
break |
||||
|
||||
except (ValueError, IndexError): |
||||
pass |
||||
|
||||
if __name__ == '__main__': |
||||
import argparse |
||||
|
||||
parser = argparse.ArgumentParser( |
||||
formatter_class=argparse.RawDescriptionHelpFormatter, |
||||
description=__doc__, |
||||
) |
||||
parser.add_argument('-d', '--dump', action='store_true', |
||||
help='dump EPUB to text') |
||||
parser.add_argument('-c', '--cols', action='store', type=int, default=float("+inf"), |
||||
help='Number of columns to wrap; default is no wrapping.') |
||||
parser.add_argument('EPUB', help='view EPUB') |
||||
args = parser.parse_args() |
||||
|
||||
if args.EPUB: |
||||
if args.dump: |
||||
dump_epub(args.EPUB, args.cols) |
||||
else: |
||||
try: |
||||
curses.wrapper(curses_epub, args.EPUB) |
||||
except KeyboardInterrupt: |
||||
pass |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh |
||||
# h2t, convert all htm and html files of a directory to text |
||||
|
||||
for file in `ls *.htm` |
||||
do |
||||
new=`basename $file htm` |
||||
lynx -dump $file > ${new}txt |
||||
done |
||||
##### |
||||
for file in `ls *.html` |
||||
do |
||||
new=`basename $file html` |
||||
lynx -dump $file > ${new}txt |
||||
done |
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh |
||||
# Thumbnails for something, invocation from workingdir |
||||
make_thumbnail() { |
||||
pic=$1 |
||||
thumb=$(dirname "$1")/thumb-$(basename "$1") |
||||
convert "$pic" -thumbnail x150 "$thumb" |
||||
} |
||||
|
||||
for pic in ./*.png |
||||
do |
||||
make_thumbnail "$pic" |
||||
done |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash |
||||
|
||||
read_epub() |
||||
{ |
||||
einfo -q -p $1 | elinks -force-html -dump |
||||
} |
||||
|
||||
read_html() |
||||
{ |
||||
elinks -dump $1 |
||||
} |
||||
|
||||
read_txt() |
||||
{ |
||||
cat $1 |
||||
} |
||||
|
||||
view_txt() |
||||
{ |
||||
book="$(dialog --backtitle "Choose a text file" --fselect $HOME 0 0 --stdout)" |
||||
dialog --backtitle "$book" --textbox $book 0 0 |
||||
} |
||||
|
||||
view_html() |
||||
{ |
||||
book="$(dialog --backtitle "Choose an HTML file" --fselect $HOME 0 0 --stdout)" |
||||
read_html $book > $HOME/.etemp.txt |
||||
dialog --backtitle "$1" --textbox $HOME/.etemp.txt 0 0 |
||||
rm $HOME/.etemp.txt |
||||
} |
||||
|
||||
show_metadata() |
||||
{ |
||||
einfo $1 |
||||
} |
||||
|
||||
view_epub() |
||||
{ |
||||
book="$(dialog --backtitle "Choose a book" --fselect $HOME/Books/ 0 0 --stdout)" |
||||
read_epub $book > $HOME/.etemp.txt |
||||
dialog --backtitle "$book" --textbox $HOME/.etemp.txt 0 0 |
||||
rm $HOME/.etemp.txt |
||||
} |
||||
|
||||
do_help() |
||||
{ |
||||
cat << EOF |
||||
Usage: |
||||
|
||||
$0 -r {epub,html,txt} file | less |
||||
|
||||
Dump a file according to specified format to standard output for pagers like less. |
||||
|
||||
$0 -m file |
||||
|
||||
Show an ePub book's metadata. |
||||
|
||||
$0 -v {epub,html,txt} |
||||
|
||||
Select and read a file via curses dialogs. |
||||
|
||||
$0 -h |
||||
|
||||
Display this help page. |
||||
EOF |
||||
} |
||||
|
||||
if [ -e ~/.pubreader.rc ];then |
||||
source ~/.pubreader.rc |
||||
else |
||||
cat > ~/.pubreader.rc << EOF |
||||
#add new functions below |
||||
EOF |
||||
source ~/.pubreader.rc |
||||
fi |
||||
|
||||
while getopts "r:m:v:h" option;do |
||||
case "$option" in |
||||
r) read_${OPTARG} $3;; |
||||
m) show_metadata ${OPTARG};; |
||||
v) view_${OPTARG};; |
||||
h) do_help;; |
||||
esac |
||||
done |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash |
||||
# renames.sh |
||||
# basic file renamer |
||||
|
||||
for file in *.png |
||||
do |
||||
mv "$file" "p${file%.png}.png" |
||||
done |
||||
for file in *.jpg |
||||
do |
||||
mv "$file" "p${file%.jpg}.jpg" |
||||
|
||||
done |
@ -0,0 +1,141 @@
@@ -0,0 +1,141 @@
|
||||
#!/bin/dash |
||||
|
||||
NAME="tuxalarm.sh" |
||||
AUTHOR="Craciun Dan" |
||||
HTTP="http://www.tuxarena.com/intro/tuxalarm.php" |
||||
MAIL="floydian.embryo@yahoo.com" |
||||
VERSION="0.2.0" |
||||
DATE="Feb 15, 2014" |
||||
LICENSE="GPLv2" |
||||
|
||||
# TODO: make a cli music player using gstreamer and use that instead of avplay |
||||
|
||||
alarm1="Replace this with the absolute path to an audio file (e.g. $HOME/Music/alarm.mp3)." |
||||
alarm2="Replace this with the absolute path to an audio file (e.g. $HOME/Music/alarm.mp3)." |
||||
alarm3="Replace this with the absolute path to a directory containing audio files." |
||||
interval="5" |
||||
|
||||
bin_ogg123=0 |
||||
bin_avplay=0 |
||||
|
||||
if [ -x /usr/bin/ogg123 ]; then |
||||
#bin_ogg123=1 |
||||
bin_ogg123=0 # set this to 1 to use ogg123 instead of avplay |
||||
# or replace all ogg123 occurences with mpg123; ogg123 plays only ogg and flac files |
||||
fi |
||||
if [ -x /usr/bin/avplay ]; then |
||||
bin_avplay=1 |
||||
fi |
||||
|
||||
if [ $bin_ogg123 -eq 0 ] && [ $bin_avplay -eq 0 ]; then |
||||
echo "WARNING: No suitable player found. The alarm will NOT work! (Tip: install vorbis-tools or avplay)" |
||||
echo "Exiting..." |
||||
exit 0 |
||||
fi |
||||
|
||||
echo -n "Enter alarm time as HHMM format (e.g. 0620 for 6:20 AM): " |
||||
read alarm |
||||
|
||||
echo "Available alarms:" |
||||
echo "1. $alarm1" |
||||
echo "2. $alarm2" |
||||
echo "3. All files inside $alarm3" |
||||
|
||||
valid=0 |
||||
while [ $valid -eq 0 ]; do |
||||
echo -n "Choose alarm file (default 1): " |
||||
read input |
||||
if [ "$input" = "1" ] || [ "$input" = "" ]; then |
||||
valid=1 |
||||
default=1 |
||||
elif [ "$input" = "2" ]; then |
||||
valid=1 |
||||
default=2 |
||||
elif [ "$input" = "3" ]; then |
||||
found=0 |
||||
for i in $alarm3/*.ogg; do |
||||
if [ -f $i ]; then |
||||
found=1 |
||||
fi |
||||
done |
||||
for i in $alarm3/*.mp3; do |
||||
if [ -f $i ]; then |
||||
found=1 |
||||
fi |
||||
done |
||||
if [ $found -eq 1 ]; then |
||||
valid=1 |
||||
default=3 |
||||
else |
||||
echo "No .ogg or .mp3 files found inside $alarm3! Change the directory or the alarm will NOT work!" |
||||
echo "Exiting..." |
||||
exit 0 |
||||
fi |
||||
fi |
||||
done |
||||
|
||||
printalarm () { |
||||
if [ $bin_ogg123 -eq 1 ]; then |
||||
if [ $default -eq 1 ]; then |
||||
echo ogg123 $alarm1 |
||||
elif [ $default -eq 2 ]; then |
||||
echo ogg123 $alarm2 |
||||
else |
||||
echo ogg123 $alarm3/* |
||||
fi |
||||
elif [ $bin_avplay -eq 1 ]; then |
||||
if [ $default -eq 1 ]; then |
||||
echo avplay -nodisp -autoexit $alarm1 |
||||
elif [ $default -eq 2 ]; then |
||||
echo avplay -nodisp -autoexit $alarm2 |
||||
else |
||||
echo avplay -nodisp -autoexit $alarm3'/*' |
||||
fi |
||||
fi |
||||
} |
||||
|
||||
echo "" |
||||
echo "Alarm time: $alarm" |
||||
echo "Repeat interval: $interval" |
||||
echo -n "Command: " |
||||
printalarm |
||||
echo "" |
||||
|
||||
playalarm () { |
||||
if [ $bin_ogg123 -eq 1 ]; then |
||||
if [ $default -eq 1 ]; then |
||||
ogg123 $alarm1 |
||||
elif [ $default -eq 2 ]; then |
||||
ogg123 $alarm2 |
||||
else |
||||
ogg123 $alarm3/*.ogg |
||||
fi |
||||
elif [ $bin_avplay -eq 1 ]; then |
||||
if [ $default -eq 1 ]; then |
||||
avplay -nodisp -autoexit $alarm1 |
||||
elif [ $default -eq 2 ]; then |
||||
avplay -nodisp -autoexit $alarm2 |
||||
else |
||||
for i in $alarm3/*; do |
||||
avplay -nodisp -autoexit $i |
||||
done |
||||
fi |
||||
fi |
||||
sleep $interval |
||||
} |
||||
|
||||
passed=0 |
||||
while [ $passed -eq 0 ]; do |
||||
if [ `date +"%H%M"` = "$alarm" ]; then |
||||
passed=1 |
||||
echo "Rise and shine! It is `date +"%A %b %d, %Y %H:%M"`. (Press ^C to stop the alarm)\n" |
||||
|
||||
while [ 1 ]; do |
||||
playalarm |
||||
done |
||||
fi |
||||
sleep 10 |
||||
done |
||||
|
||||
# ChangeLog |
||||
# v0.2.0 (Feb 15, 2014) - initial release |
Loading…
Reference in new issue