diff --git a/papers/commands/add_cmd.py b/papers/commands/add_cmd.py index d870d3a..b73d599 100644 --- a/papers/commands/add_cmd.py +++ b/papers/commands/add_cmd.py @@ -7,6 +7,7 @@ except ImportError: from .. import color from .. import files from .. import pretty +from .. import repo def parser(subparsers, config): @@ -28,7 +29,7 @@ def command(config, pdffile, bibfile): files.check_file(fullbibpath) filename, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) - if ext != '.pdf' and ext != '.ps': + if ext != '.pdf' and ext != '.ps': print('{}warning{}: extention {}{}{} not recognized{}'.format( color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) @@ -53,8 +54,8 @@ def command(config, pdffile, bibfile): papers.set('header', 'count', int(count) + 1) citekey = pretty.create_citekey(bib_data) - papers.set('papers', citekey, filename) - papers.set('citekeys', 'ck' + count, citekey) + papers.set('citekeys', citekey, filename) + papers.set('numbers', 'ck' + count, citekey) files.write_papers(papers) files.write_meta(meta, filename) diff --git a/papers/commands/init_cmd.py b/papers/commands/init_cmd.py index 136c7bb..f38bc5e 100644 --- a/papers/commands/init_cmd.py +++ b/papers/commands/init_cmd.py @@ -29,8 +29,8 @@ def command(config): papers = configparser.ConfigParser() papers.add_section('header') papers.set('header', 'count', 0) - papers.add_section('papers') papers.add_section('citekeys') + papers.add_section('numbers') files.write_papers(papers) else: diff --git a/papers/commands/list_cmd.py b/papers/commands/list_cmd.py index f3e0dfe..fe8da92 100644 --- a/papers/commands/list_cmd.py +++ b/papers/commands/list_cmd.py @@ -1,24 +1,21 @@ -from .. import files -from .. import pretty -from .. import color - import subprocess import tempfile +from .. import pretty +from .. import color +from .. import repo + def parser(subparsers, config): parser = subparsers.add_parser('list', help="list all papers") return parser def command(config): - papers = files.load_papers() - + rp = repo.Repository() + articles = [] - for p in papers.options('citekeys'): - number = p[2:] - citekey = papers.get('citekeys', p) - filename = papers.get('papers', citekey) - bibdata = files.load_bibdata(filename + '.bibyaml') - bibdesc = pretty.bib_oneliner(bibdata) + for n in rp.numbers: + paper = paper_from_number(n, fatal = True) + bibdesc = pretty.bib_oneliner(paper.bibdata) articles.append('{:3d} {}{}{}{} {}'.format(int(number), color.purple, citekey, color.end, (8-len(citekey))*' ', bibdesc)) with tempfile.NamedTemporaryFile(suffix=".tmp", delete=True) as tmpf: diff --git a/papers/commands/open_cmd.py b/papers/commands/open_cmd.py index 983da8a..9780751 100644 --- a/papers/commands/open_cmd.py +++ b/papers/commands/open_cmd.py @@ -1,30 +1,17 @@ -try: - import ConfigParser as configparser -except ImportError: - import configparser import subprocess -from .. import files from .. import color +from .. import repo 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") + parser = subparsers.add_parser('open', help='{}open the paper in a pdf viewer{}'.format(color.normal, color.end)) + parser.add_argument('citekey', help='{}the paper associated citekey{}'.format(color.normal, color.end)) return parser def command(config, citekey): - papers = files.load_papers() - try: - filename = papers.get('papers', str(citekey)) - except configparser.NoOptionError: - try: - ck = papers.get('citekeys', 'ck'+str(citekey)) - filename = papers.get('papers', str(ck)) - except configparser.NoOptionError: - print('{}error{}: paper with citekey or number {}{}{} not found{}'.format( - color.red, color.grey, color.cyan, citekey, color.grey, color.end)) - exit(-1) - meta_data = files.load_meta(filename) - filepath = meta_data.get('metadata', 'path') + rp = repo.Repository() + paper = rp.paper_from_any(citekey, fatal = True) + filepath = paper.metadata.get('metadata', 'path') + p = subprocess.Popen(['open', filepath]) - print('{}{}{} opened.{}'.format(color.cyan, filepath, color.grey, color.end)) \ No newline at end of file + print('{}{}{} opened.{}'.format(color.filepath, filepath, color.normal, color.end)) \ No newline at end of file diff --git a/papers/files.py b/papers/files.py index bbe2ef4..8245c9a 100644 --- a/papers/files.py +++ b/papers/files.py @@ -110,7 +110,7 @@ def load_papers(): return read_configfile(find_papersdir() + os.sep + 'papers') def load_bibdata(filename): - fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + fullbibpath = find_papersdir() + os.sep + 'bibdata' + os.sep + filename + '.bibyaml' return load_externalbibfile(fullbibpath) def write_bibdata(bib_data, filename): diff --git a/papers/paper.py b/papers/paper.py new file mode 100644 index 0000000..305d0ed --- /dev/null +++ b/papers/paper.py @@ -0,0 +1,23 @@ +import files +import color + +class Paper(object): + """Paper class. The object is responsible for the integrity of its own data, + and for loading and writing it to disc. + """ + + @classmethod + def from_disc(cls, name): + p = Paper(name) + self.bib_data = files.load_bibdata(self.name) + self.metadata = files.load_meta(self.name) + self.citekey = self.metadata.get('metadata', 'citekey') + self.number = self.metadata.get('metadata', 'number') + return p + + def __init__(self, name): + self.name = name + + + + diff --git a/papers/pretty.py b/papers/pretty.py index 9b48790..bbad9aa 100644 --- a/papers/pretty.py +++ b/papers/pretty.py @@ -26,33 +26,3 @@ def bib_desc(bib_data): s += '\n' s += '\n'.join('{}: {}'.format(k, v) for k, v in article.fields.items()) return s - -alphabet = 'abcdefghijklmopqrstuvwxyz' - -try: - import ConfigParser as configparser -except ImportError: - import configparser -import files - -def create_citekey(bib_data): - """Create a cite key unique to the paper""" - article = bib_data.entries[list(bib_data.entries.keys())[0]] - first_author = article.persons['author'][0] - year = article.fields['year'] - prefix = '{}{}'.format(first_author.last()[0][:6], year[2:]) - - papers = files.load_papers() - letter = 0, False - citekey = None - - citekey = prefix - while not letter[1]: - try: - papers.get('papers', citekey) - citekey = prefix + alphabet[letter[0]] - letter = letter[0]+1, False - except configparser.NoOptionError: - letter = letter[0], True - - return citekey diff --git a/papers/repo.py b/papers/repo.py new file mode 100644 index 0000000..cf436ae --- /dev/null +++ b/papers/repo.py @@ -0,0 +1,130 @@ +try: + import ConfigParser as configparser +except ImportError: + import configparser + +from paper import Paper + +alphabet = 'abcdefghijklmopqrstuvwxyz' + + +class Repository(object): + + def __init__(self): + self.paperdir = files.find_papersdir() + self.papers_config = files.load_papers() + self.citekeys = dict(ck, None for ck in self.paper_config.options('citekeys') + self.numbers = sorted(n[2:] for n in self.paper_config.options('numbers')) + + # loading existing papers + + def paper_from_number(self, number, fatal = True): + try: + citekey = self.papers_config.get('numbers', 'ck'+number) + return self.load_paper(citekey) + except configparser.NoOptionError: + if fatal: + print('{}error{}: no paper with number {}{}{}'.format( + color.error, color.normal, color.citekey, citekey, color.end) + exit(-1) + raise IOError, 'file not found' + + def paper_from_citekey(self, citekey, fatal = True): + """Load a paper by its citekey from disk, if necessary.""" + try: + paper = self.citekeys[citekey] + if paper is None: + name = self.papers_config.get('citekeys', citekey) + paper = Paper.from_disc(name) + self.citekeys[citekey] = paper + return paper + except KeyError: + if fatal: + print('{}error{}: no paper with citekey {}{}{}'.format( + color.error, color.normal, color.citekey, citekey, color.end) + exit(-1) + raise IOError, 'file not found' + + def paper_from_any(self, key, fatal = True): + try: + return rp.paper_from_citekey(key, fatal = False) + except IOError: + try: + return rp.paper_from_number(key, fatal = False) + except IOError: + if fatal: + print('{}error{}: paper with citekey or number {}{}{} not found{}'.format( + color.error, color.normal, color.citekey, key, color.normal, color.end)) + exit(-1) + raise IOError, 'file not found' + + # creating new papers + + def add_paper(self, pdffile, bibfile): + + fullpdfpath = os.path.abspath(pdffile) + fullbibpath = os.path.abspath(bibfile) + files.check_file(fullpdfpath) + files.check_file(fullbibpath) + + name, ext = os.path.splitext(os.path.split(fullpdfpath)[1]) + if ext != '.pdf' and ext != '.ps': + print('{}warning{}: extension {}{}{} not recognized{}'.format( + color.yellow, color.grey, color.cyan, ext, color.grey, color.end)) + + # creating meta file + meta = create_meta(fullpdfpath, name, ext, bib_data) + + # creating bibyaml file + bib_data = files.load_externalbibfile(fullbibpath) + print('{}bibliographic data present in {}{}{}'.format( + color.grey, color.cyan, bibfile, color.end)) + print(pretty.bib_desc(bib_data)) + + # updating papersconfig + citekey = pretty.create_citekey(bib_data) + papers.set('citekeys', citekey, name) + papers.set('numbers', 'ck' + count, citekey) + + # writing all to disk + files.write_bibdata(bib_data, name) + files.write_papers(papers) + files.write_meta(meta, name) + + def create_meta(self, path, name, ext, bib_data): + citekey = create_citekey(bib_data, allowed = (,)) + number = create_number() + + meta = configparser.ConfigParser() + meta.add_section('metadata') + + meta.set('metadata', 'name', name) + meta.set('metadata', 'extension', ext) + meta.set('metadata', 'path', os.path.normpath(fullpdfpath)) + + meta.add_section('notes') + + return meta + + def create_citekey(self, bib_data, allowed = (,)): + """Create a cite key unique to a given bib_data""" + article = bib_data.entries[list(bib_data.entries.keys())[0]] + first_author = article.persons['author'][0] + year = article.fields['year'] + prefix = '{}{}'.format(first_author.last()[0][:6], year[2:]) + + letter = 0, False + citekey = None + + citekey = prefix + while citekey in self.citekeys and citekey not in allowed: + citekey = prefix + alphabet[letter[0]] + letter += 1 + + return citekey + + def create_number(self, bib_data, allowed = []): + count = self.papers_config.get('header', 'count') + self.papers_config.set('header', 'count', count + 1) + return count + \ No newline at end of file