You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

248 lines
7.7 KiB

#!/usr/bin/env python
import sys, os
import datetime
import shutil
import tempfile
import textwrap
from subprocess import call
import webbrowser
import urllib
import ConfigParser
import yaml
try:
import pybtex
import pybtex.database
import pybtex.database.input
import pybtex.database.input.bibtex
import pybtex.database.input.bibtexml
import pybtex.database.input.bibyaml
import pybtex.database.output
import pybtex.database.output.bibtex
import pybtex.database.output.bibtexml
import pybtex.database.output.bibyaml
except ImportError:
print '{}error{}: you need to install Pybtex; try running \'pip install pybtex\'.'.format(red, end)
# display
bold = '\033[1m'
end = '\033[0m'
black = '\033[0;30m'
red = '\033[0;31m'
green = '\033[0;32m'
yellow = '\033[0;33m'
blue = '\033[0;34m'
purple = '\033[0;35m'
cyan = '\033[0;36m'
grey = '\033[0;37m'
# Bold
bblack = '\033[1;30m'
bred = '\033[1;31m'
bgreen = '\033[1;32m'
byellow = '\033[1;33m'
bblue = '\033[1;34m'
bpurple = '\033[1;35m'
bcyan = '\033[1;36m'
bgrey = '\033[1;37m'
# utility functions
currentdir = os.getcwd()
papersdir = None
def find_papersdir():
global papersdir
curdir = os.path.abspath(os.getcwd())
while curdir != '':
if os.path.exists(curdir + '/.papers') and os.path.isdir(curdir + '/.papers'):
papersdir = curdir + '/.papers'
curdir = ''
if curdir == '/':
curdir = ''
else:
curdir = os.path.split(curdir)[0]
if papersdir is None:
print '{}error{} : no papers repo found in this directory or in any parent directory.{}'.format(red, grey, end)
exit(0)
def vim_input(initial = ""):
"""Use an editor to get input"""
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=False) as temp_file:
tfile_name = temp_file.name
temp_file.write(initial)
temp_file.flush()
call([EDITOR, tfile_name])
with open(tfile_name) as temp_file:
content = temp_file.read()
os.remove(tfile_name)
return content
def load_externalbibfile(fullbibpath):
check_file(fullbibpath)
filename, ext = os.path.splitext(os.path.split(fullbibpath)[1])
if ext == '.bib':
parser = pybtex.database.input.bibtex.Parser()
bib_data = parser.parse_file(fullbibpath)
elif ext == '.xml' or ext == '.bibtexml':
parser = pybtex.database.input.bibtexml.Parser()
bib_data = parser.parse_file(fullbibpath)
elif ext == '.yaml' or ext == '.bibyaml':
parser = pybtex.database.input.bibyaml.Parser()
bib_data = parser.parse_file(fullbibpath)
else:
print '{}error{}: {}{}{} not recognized format for bibliography{}'.format(red, grey, cyan, ext, grey, end)
return bib_data
def load_bibfile(filename):
fullbibpath = papersdir + os.sep + 'bibdata' + os.sep + filename
return load_externalbibfile(fullbibpath)
def write_bibfile(bib_data, filename):
filepath = papersdir + os.sep + 'bibdata' + os.sep + filename + '.bibyaml'
with open(filepath, 'w') as f:
parser = pybtex.database.output.bibyaml.Writer()
parser.write_stream(bib_data, f)
def write_meta(meta_data, filename):
filepath = papersdir + os.sep + 'meta' + os.sep + filename + '.meta'
with open(filepath, 'w') as f:
meta_data.write(f)
def check_file(filepath):
if not os.path.exists(filepath):
print '{}error{}: {}{}{} does not exists{}'.format(red, grey, cyan, filepath, grey, end)
exit(-1)
if not os.path.isfile(filepath):
print '{}error{}: {}{}{} is not a file{}'.format(red, grey, cyan, filepath, grey, end)
exit(-1)
def person_repr(p):
return ' '.join(s for s in [' '.join(p.first(abbr = True)),
' '.join(p.middle(abbr = True)),
' '.join(p.prelast(abbr = False)),
' '.join(p.last(abbr = False)),
' '.join(p.lineage(abbr = True))] if s)
def bib_desc(bib_data):
article = bib_data.entries[list(bib_data.entries.keys())[0]]
authors = ', '.join(person_repr(p) for p in article.persons['author'])
title = article.fields['title']
year = article.fields['year']
journal = article.fields['journal']
return '{}{}{} \"{}{}{}\" {}{}{} {}({}{}{}){}'.format(green, authors, grey, bcyan, title, grey, yellow, journal, end, grey, end, year, grey, end)
# commands
def init_cmd():
"""Create a .papers directory"""
# create dir
papersdir = os.getcwd() + '/.papers'
if not os.path.exists(papersdir):
print '{}initializing papers in {}{}{}'.format(grey, cyan, papersdir, end)
os.makedirs(papersdir)
os.makedirs(papersdir+os.sep+'bibdata')
os.makedirs(papersdir+os.sep+'meta')
else:
print '{}error{} : papers already present in {}{}{}'.format(red, grey, cyan, papersdir, end)
exit(-1)
def install_cmd():
"""Install command on the system"""
print '{}file to install : {}{}{}'.format(grey, cyan, __file__, end)
default = '/usr/local/bin'
print "{}folder to install the papers command [{}{:s}{}] : {}".format(grey, cyan, default, grey, end),
sys.stdout.flush()
path = raw_input()
if path == '':
path = default
if not os.path.exists(path):
print "{}error{}: {}{:s}{} does not exist - installation aborted".format(red, end, cyan, path, end)
else:
if os.path.exists(path+'/papers'):
if os.path.samefile(path+'/papers', __file__):
return
shutil.copy(__file__, path)
def websearch_cmd(search_string):
url = 'https://scholar.google.fr/scholar?hl=fr&q={}&lr='.format(urllib.quote_plus(search_string))
webbrowser.open(url)
def add_cmd(pdffilepath, bibtex = None):
"""
:param pdffilepath path (no url yet) to a pdf or ps file
:param bibtex bibtex file (in .bib, .bibml or .yaml format.
"""
fullpdfpath = os.path.abspath(pdffilepath)
fullbibpath = os.path.abspath(bibtex)
check_file(fullpdfpath)
check_file(fullbibpath)
filename, ext = os.path.splitext(os.path.split(fullpdfpath)[1])
if ext != '.pdf' and ext != '.ps':
print '{}warning{}: extention {}{}{} not recognized{}'.format(yellow, grey, cyan, ext, grey, end)
meta = ConfigParser.ConfigParser()
meta.add_section('metadata')
meta.set('metadata', 'filename', filename)
meta.set('metadata', 'extension', ext)
meta.set('metadata', 'path', os.path.normpath(fullpdfpath))
meta.add_section('notes')
if bibtex is not None:
bib_data = load_externalbibfile(fullbibpath)
write_bibfile(bib_data, filename)
write_meta(meta, filename)
def list_cmd():
files = os.listdir(papersdir + os.sep + 'bibdata')
articles = []
for filename in files:
bibdata = load_bibfile(filename)
bibdesc = bib_desc(bibdata)
articles.append(str(bibdesc))
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf:
tmpf.write('\n'.join(articles))
tmpf.flush()
call(['less', '-XRF', tmpf.name])
# argument parsing (old school)
cmds = {'init': init_cmd,
'install': install_cmd,
'websearch': websearch_cmd,
'add': add_cmd,
'list': list_cmd,
}
error_msg = "{}banana {}banana {}banana{}".format(purple, yellow, cyan, end)
if len(sys.argv) == 1:
print error_msg
else:
cmd = sys.argv[1]
if cmd in cmds and cmd not in ['init', 'install', 'websearch']:
find_papersdir()
try:
args = sys.argv[2:]
cmds[cmd](*args)
except KeyError, TypeError:
print error_msg