divided code into multiple files paperpile style argparse setup.py with script optionmain
parent
60d17982e4
commit
acab1b8044
@ -0,0 +1,2 @@
|
|||||||
|
build/
|
||||||
|
*.pyc
|
@ -0,0 +1,6 @@
|
|||||||
|
A paper correspond to 3 files :
|
||||||
|
name.pdf a pdf or ps file, the paper itself, whose location is arbitrary
|
||||||
|
bibdata/name.bibyaml a bibyaml file with all bibliographic data.
|
||||||
|
meta/name.meta a metadata file for internal use, notes, citekeys, status, etc.
|
||||||
|
|
||||||
|
|
@ -1,318 +0,0 @@
|
|||||||
#!/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
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
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
|
|
||||||
try:
|
|
||||||
EDITOR = os.environ['EDITOR']
|
|
||||||
except KeyError:
|
|
||||||
EDITOR = 'nano'
|
|
||||||
|
|
||||||
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 write_configfile(config, filepath):
|
|
||||||
try:
|
|
||||||
with open(filepath, 'w') as f:
|
|
||||||
config.write(f)
|
|
||||||
except IOError as e:
|
|
||||||
print '{}error{} : impossible to write on file {}{:s}{}'.format(red, grey, cyan, filepath, end)
|
|
||||||
print 'Verify permissions'
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
def write_papers(config):
|
|
||||||
write_configfile(config, papersdir + os.sep + 'papers')
|
|
||||||
|
|
||||||
def read_configfile(filepath):
|
|
||||||
try:
|
|
||||||
with open(filepath, 'r') as f:
|
|
||||||
config = ConfigParser.ConfigParser()
|
|
||||||
config.readfp(f)
|
|
||||||
return config
|
|
||||||
except IOError as e:
|
|
||||||
print '{}error{} : impossible to read file {}{:s}{}'.format(red, grey, cyan, filepath, end)
|
|
||||||
print 'Verify permissions'
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
def read_papers():
|
|
||||||
return read_configfile(papersdir + os.sep + 'papers')
|
|
||||||
|
|
||||||
|
|
||||||
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'
|
|
||||||
write_configfile(meta_data, filepath)
|
|
||||||
|
|
||||||
def load_meta(filename):
|
|
||||||
filepath = papersdir + os.sep + 'meta' + os.sep + filename + '.meta'
|
|
||||||
return read_configfile(filepath)
|
|
||||||
|
|
||||||
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_oneliner(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)
|
|
||||||
|
|
||||||
def bib_desc(bib_data):
|
|
||||||
article = bib_data.entries[list(bib_data.entries.keys())[0]]
|
|
||||||
s = '\n'.join('author: {}'.format(person_repr(p)) for p in article.persons['author'])
|
|
||||||
s += '\n'
|
|
||||||
s += '\n'.join('{}: {}'.format(k, v) for k, v in article.fields.items())
|
|
||||||
return s
|
|
||||||
|
|
||||||
# commands
|
|
||||||
|
|
||||||
def init_cmd():
|
|
||||||
"""Create a .papers directory"""
|
|
||||||
global papersdir
|
|
||||||
# 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')
|
|
||||||
papers = ConfigParser.ConfigParser()
|
|
||||||
papers.add_section('header')
|
|
||||||
papers.set('header', 'count', 0)
|
|
||||||
papers.add_section('papers')
|
|
||||||
write_papers(papers)
|
|
||||||
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)
|
|
||||||
print '{}bibliographic data present in {}{}{}'.format(grey, cyan, bibtex, end)
|
|
||||||
print bib_desc(bib_data)
|
|
||||||
write_bibfile(bib_data, filename)
|
|
||||||
|
|
||||||
papers = read_papers()
|
|
||||||
count = papers.get('header', 'count')
|
|
||||||
papers.set('header', 'count', int(count) + 1)
|
|
||||||
papers.set('papers', 'p' + count, filename)
|
|
||||||
write_papers(papers)
|
|
||||||
|
|
||||||
write_meta(meta, filename)
|
|
||||||
|
|
||||||
def list_cmd():
|
|
||||||
papers = read_papers()
|
|
||||||
|
|
||||||
articles = []
|
|
||||||
for p in papers.options('papers'):
|
|
||||||
filename = papers.get('papers', p)
|
|
||||||
number = p[1:]
|
|
||||||
bibdata = load_bibfile(filename + '.bibyaml')
|
|
||||||
bibdesc = bib_oneliner(bibdata)
|
|
||||||
articles.append('{:3d} {}'.format(int(number), bibdesc))
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf:
|
|
||||||
tmpf.write('\n'.join(articles))
|
|
||||||
tmpf.flush()
|
|
||||||
call(['less', '-XRF', tmpf.name])
|
|
||||||
|
|
||||||
def open_cmd(number):
|
|
||||||
papers = read_papers()
|
|
||||||
filename = papers.get('papers', 'p' + str(number))
|
|
||||||
meta_data = load_meta(filename)
|
|
||||||
filepath = meta_data.get('metadata', 'path')
|
|
||||||
p = subprocess.Popen(['open', filepath])
|
|
||||||
print '{}{}{} opened.{}'.format(cyan, filepath, grey, end)
|
|
||||||
|
|
||||||
# argument parsing (old school)
|
|
||||||
|
|
||||||
cmds = {'init': init_cmd,
|
|
||||||
'install': install_cmd,
|
|
||||||
'websearch': websearch_cmd,
|
|
||||||
'add': add_cmd,
|
|
||||||
'list': list_cmd,
|
|
||||||
'open': open_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()
|
|
||||||
|
|
||||||
args = sys.argv[2:]
|
|
||||||
cmds[cmd](*args)
|
|
||||||
# try:
|
|
||||||
# args = sys.argv[2:]
|
|
||||||
# cmds[cmd](*args)
|
|
||||||
# except KeyError, TypeError:
|
|
||||||
# print error_msg
|
|
||||||
#
|
|
@ -0,0 +1,23 @@
|
|||||||
|
# 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'
|
@ -0,0 +1,5 @@
|
|||||||
|
import add_cmd
|
||||||
|
import init_cmd
|
||||||
|
import list_cmd
|
||||||
|
import open_cmd
|
||||||
|
import websearch_cmd
|
@ -0,0 +1,57 @@
|
|||||||
|
from .. import color
|
||||||
|
from .. import files
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ConfigParser as configparser
|
||||||
|
except ImportError:
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parser(subparsers, config):
|
||||||
|
parser = subparsers.add_parser('add', help='add a paper to the repository')
|
||||||
|
parser.add_argument('pdffile', help='pdf or ps file')
|
||||||
|
parser.add_argument('bibfile', help='bibtex, bibtexml or bibyaml file')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def command(config, pdffile, bibfile):
|
||||||
|
"""
|
||||||
|
:param pdffilepath path (no url yet) to a pdf or ps file
|
||||||
|
:param bibtex bibtex file (in .bib, .bibml or .yaml format.
|
||||||
|
"""
|
||||||
|
papersdir = files.find_papersdir()
|
||||||
|
|
||||||
|
fullpdfpath = os.path.abspath(pdffile)
|
||||||
|
fullbibpath = os.path.abspath(bibtex)
|
||||||
|
files.check_file(fullpdfpath)
|
||||||
|
files.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(
|
||||||
|
color.yellow, color.grey, color.cyan, ext, color.grey, color.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 = files.load_externalbibfile(fullbibpath)
|
||||||
|
print('{}bibliographic data present in {}{}{}'.format(
|
||||||
|
color.grey, color.cyan, bibtex, color.end))
|
||||||
|
print(bib_desc(bib_data))
|
||||||
|
files.write_bibfile(bib_data, filename)
|
||||||
|
|
||||||
|
papers = files.read_papers()
|
||||||
|
count = papers.get('header', 'count')
|
||||||
|
papers.set('header', 'count', int(count) + 1)
|
||||||
|
papers.set('papers', 'p' + count, filename)
|
||||||
|
|
||||||
|
files.write_papers(papers)
|
||||||
|
files.write_meta(meta, filename)
|
@ -0,0 +1,37 @@
|
|||||||
|
# init command
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ConfigParser as configparser
|
||||||
|
except ImportError:
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from .. import color
|
||||||
|
from .. import files
|
||||||
|
|
||||||
|
def parser(subparsers, config):
|
||||||
|
parser = subparsers.add_parser('init', help="initialize the .papers directory")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def command(config):
|
||||||
|
"""Create a .papers directory"""
|
||||||
|
# create dir
|
||||||
|
papersdir = os.getcwd() + '/.papers'
|
||||||
|
|
||||||
|
if not os.path.exists(papersdir):
|
||||||
|
print('{}initializing papers in {}{}{}'.format(
|
||||||
|
color.grey, color.cyan, papersdir, color.end))
|
||||||
|
|
||||||
|
os.makedirs(papersdir)
|
||||||
|
os.makedirs(papersdir+os.sep+'bibdata')
|
||||||
|
os.makedirs(papersdir+os.sep+'meta')
|
||||||
|
|
||||||
|
papers = configparser.ConfigParser()
|
||||||
|
papers.add_section('header')
|
||||||
|
papers.set('header', 'count', 0)
|
||||||
|
papers.add_section('papers')
|
||||||
|
files.write_papers(papers)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('{}error {} : papers already present in {}{}{}'.format(
|
||||||
|
color.red, color.grey, color.cyan, papersdir, color.end))
|
||||||
|
exit(-1)
|
@ -0,0 +1,25 @@
|
|||||||
|
# install command
|
||||||
|
|
||||||
|
# Probably useless if setup.py is provided
|
||||||
|
|
||||||
|
#import shutil
|
||||||
|
# def parser(subparsers, config):
|
||||||
|
# parser = subparsers.add_parser('install', help="install papers on the system")
|
||||||
|
# return parser
|
||||||
|
#
|
||||||
|
# def command():
|
||||||
|
# """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)
|
@ -0,0 +1,25 @@
|
|||||||
|
from .. import files
|
||||||
|
from .. import pretty
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
def parser(subparsers, config):
|
||||||
|
parser = subparsers.add_parser('list', help="list all papers")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def command(config):
|
||||||
|
papers = files.read_papers()
|
||||||
|
|
||||||
|
articles = []
|
||||||
|
for p in papers.options('papers'):
|
||||||
|
filename = papers.get('papers', p)
|
||||||
|
number = p[1:]
|
||||||
|
bibdata = files.load_bibdata(filename + '.bibyaml')
|
||||||
|
bibdesc = pretty.bib_oneliner(bibdata)
|
||||||
|
articles.append('{:3d} {}'.format(int(number), bibdesc))
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf:
|
||||||
|
tmpf.write('\n'.join(articles))
|
||||||
|
tmpf.flush()
|
||||||
|
subprocess.call(['less', '-XRF', tmpf.name])
|
@ -0,0 +1,17 @@
|
|||||||
|
from .. import files
|
||||||
|
from .. import color
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def parser(subparsers, config):
|
||||||
|
parser = subparsers.add_parser('open', help="open the paper in a pdf viewer")
|
||||||
|
parser.add_argument("citekey", help="the paper associated citekey")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def command(config, citekey):
|
||||||
|
papers = files.read_papers()
|
||||||
|
filename = papers.get('papers', 'p' + str(citekey))
|
||||||
|
meta_data = files.load_meta(filename)
|
||||||
|
filepath = meta_data.get('metadata', 'path')
|
||||||
|
p = subprocess.Popen(['open', filepath])
|
||||||
|
print('{}{}{} opened.{}'.format(color.cyan, filepath, color.grey, color.end))
|
@ -0,0 +1,11 @@
|
|||||||
|
import webbrowser
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
def parser(subparsers, config):
|
||||||
|
parser = subparsers.add_parser('websearch', help="launch a search on Google Scholar")
|
||||||
|
parser.add_argument("search_string", help="the search query (anything googly is possible)")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def command(config, search_string):
|
||||||
|
url = 'https://scholar.google.fr/scholar?q={}&lr='.format(urllib.quote_plus(search_string))
|
||||||
|
webbrowser.open(url)
|
@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
import sys, os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
try:
|
||||||
|
import ConfigParser as configparser
|
||||||
|
except ImportError:
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
import color
|
||||||
|
|
||||||
|
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\' or \'easy_install pybtex\''.format(color.red, color.end)
|
||||||
|
|
||||||
|
|
||||||
|
_papersdir = None
|
||||||
|
|
||||||
|
def find_papersdir():
|
||||||
|
"""Find .papers directory in this directory and the parent directories"""
|
||||||
|
global _papersdir
|
||||||
|
if _papersdir is None:
|
||||||
|
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(
|
||||||
|
color.red, color.grey, color.end)
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
return _papersdir
|
||||||
|
|
||||||
|
|
||||||
|
def check_file(filepath):
|
||||||
|
if not os.path.exists(filepath):
|
||||||
|
print '{}error{}: {}{}{} does not exists{}'.format(
|
||||||
|
color.red, color.grey, color.cyan, filepath, color.grey, color.end)
|
||||||
|
exit(-1)
|
||||||
|
if not os.path.isfile(filepath):
|
||||||
|
print '{}error{}: {}{}{} is not a file{}'.format(
|
||||||
|
color.red, color.grey, color.cyan, filepath, color.grey, color.end)
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def write_configfile(config, filepath):
|
||||||
|
try:
|
||||||
|
with open(filepath, 'w') as f:
|
||||||
|
config.write(f)
|
||||||
|
except IOError as e:
|
||||||
|
print '{}error{} : impossible to write on file {}{:s}{}'.format(
|
||||||
|
color.red, color.grey, color.cyan, filepath, color.end)
|
||||||
|
print 'Verify permissions'
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def read_configfile(filepath):
|
||||||
|
try:
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.readfp(f)
|
||||||
|
return config
|
||||||
|
except IOError as e:
|
||||||
|
print '{}error{} : impossible to read file {}{:s}{}'.format(
|
||||||
|
color.red, color.grey, color.cyan, filepath, color.end)
|
||||||
|
print 'Verify permissions'
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
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(
|
||||||
|
color.red, color.grey, color.cyan, ext, color.grey, color.end)
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
return bib_data
|
||||||
|
|
||||||
|
|
||||||
|
def write_papers(config):
|
||||||
|
write_configfile(config, find_papersdir() + os.sep + 'papers')
|
||||||
|
|
||||||
|
def read_papers():
|
||||||
|
return read_configfile(find_papersdir() + os.sep + 'papers')
|
||||||
|
|
||||||
|
def load_bibdata(filename):
|
||||||
|
fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename
|
||||||
|
return load_externalbibfile(fullbibpath)
|
||||||
|
|
||||||
|
def write_bibdata(bib_data, filename):
|
||||||
|
filepath = find_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 = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta'
|
||||||
|
write_configfile(meta_data, filepath)
|
||||||
|
|
||||||
|
def load_meta(filename):
|
||||||
|
filepath = find_papersdir() + os.sep + 'meta' + os.sep + filename + '.meta'
|
||||||
|
return read_configfile(filepath)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
EDITOR = os.environ['EDITOR']
|
||||||
|
except KeyError:
|
||||||
|
EDITOR = 'nano'
|
||||||
|
|
||||||
|
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()
|
||||||
|
subprocess.call([EDITOR, tfile_name])
|
||||||
|
|
||||||
|
with open(tfile_name) as temp_file:
|
||||||
|
content = temp_file.read()
|
||||||
|
os.remove(tfile_name)
|
||||||
|
|
||||||
|
return content
|
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import collections
|
||||||
|
|
||||||
|
import papers
|
||||||
|
from papers import commands
|
||||||
|
|
||||||
|
cmds = collections.OrderedDict([
|
||||||
|
('init', commands.init_cmd),
|
||||||
|
('add' , commands.add_cmd),
|
||||||
|
('list', commands.list_cmd),
|
||||||
|
('open', commands.open_cmd),
|
||||||
|
('websearch', commands.websearch_cmd)
|
||||||
|
])
|
||||||
|
|
||||||
|
config = None
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="research papers repository")
|
||||||
|
subparsers = parser.add_subparsers(title="valid commands", dest="command")
|
||||||
|
|
||||||
|
for cmd_mod in cmds.values():
|
||||||
|
subparser = cmd_mod.parser(subparsers, config)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.config = config
|
||||||
|
cmd = args.command
|
||||||
|
del args.command
|
||||||
|
|
||||||
|
cmds[cmd].command(**vars(args))
|
@ -0,0 +1,28 @@
|
|||||||
|
# display formatting
|
||||||
|
|
||||||
|
import color
|
||||||
|
|
||||||
|
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_oneliner(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(
|
||||||
|
color.green, authors, color.grey, color.bcyan, title, color.grey,
|
||||||
|
color.yellow, journal, color.end, color.grey, color.end, year,
|
||||||
|
color.grey, color.end)
|
||||||
|
|
||||||
|
def bib_desc(bib_data):
|
||||||
|
article = bib_data.entries[list(bib_data.entries.keys())[0]]
|
||||||
|
s = '\n'.join('author: {}'.format(person_repr(p)) for p in article.persons['author'])
|
||||||
|
s += '\n'
|
||||||
|
s += '\n'.join('{}: {}'.format(k, v) for k, v in article.fields.items())
|
||||||
|
return s
|
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from distutils.core import setup
|
||||||
|
|
||||||
|
setup(name='papers',
|
||||||
|
version='1',
|
||||||
|
author='Fabien Benureau, Olivier Mangin',
|
||||||
|
author_email='fabien.benureau+inria@gmail.com',
|
||||||
|
url='',
|
||||||
|
description='research papers manager',
|
||||||
|
requires=['pybtex'],
|
||||||
|
packages = ['papers', 'papers.commands'],
|
||||||
|
scripts=['papers/papers']
|
||||||
|
)
|
Loading…
Reference in new issue