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.

268 lines
11 KiB

import os
import shutil
import subprocess
import collections
from ... import repo
from ... import files
from ...uis import get_ui
from ...configs import config
from ...plugins import PapersPlugin
from ...events import RemoveEvent, RenameEvent
from ...commands.helpers import add_references_argument, parse_reference
from . import latex_tools
from .autofill_tools import autofill, replace_pattern
SECTION = 'texnote'
DIR = os.path.join(config().papers_dir, 'texnote')
TPL_DIR = os.path.join(DIR, 'template')
TPL_BODY = os.path.join(TPL_DIR, 'body.tex')
TPL_STYLE = os.path.join(TPL_DIR, 'style.sty')
TPL_BIB = os.path.join(TPL_DIR, 'bib.bib')
DFT_BODY = os.path.join(os.path.dirname(__file__), 'default_body.tex')
DFT_STYLE = os.path.join(os.path.dirname(__file__), 'default_style.sty')
STYLE_PATTERN = '\\usepackage{INFO}'
STYLE_INFO = os.path.splitext(TPL_STYLE)[0].replace(DIR, '')[1:]
BIB_PATTERN = '\\bibliography{INFO}'
BIB_INFO = os.path.splitext(TPL_BIB)[0].replace(DIR, '')[1:]
BIBSTYLE_PATTERN = '\\bibliographystyle{INFO}'
DFT_BIBSTYLE_INFO = 'ieeetr'
class TexnotePlugin(PapersPlugin):
name = SECTION
def __init__(self):
self.texcmds = collections.OrderedDict([
('remove', self.remove),
('edit', self.edit),
('edit_template', self.edit_template),
('generate_bib', self.generate_bib),
('clean', self.clean),
('generate_pdf', self.generate_pdf),
('extract_note', self.extract_note),
])
def _ensure_init(self):
if not files.check_directory(DIR):
os.mkdir(DIR)
if not files.check_directory(TPL_DIR):
os.mkdir(TPL_DIR)
if not files.check_file(TPL_BODY):
shutil.copy(DFT_BODY, TPL_BODY)
if not files.check_file(TPL_STYLE):
shutil.copy(DFT_STYLE, TPL_STYLE)
if not files.check_file(TPL_BIB):
self.generate_bib()
def get_commands(self, subparsers):
parser = subparsers.add_parser(self.name, help='edit advance note in latex')
sub = parser.add_subparsers(title='valid texnote commands', dest='texcmd')
# remove
p = sub.add_parser('remove', help='remove a reference')
add_references_argument(p, single=True)
p.add_argument('-f', '--force', action='store_true',
help='do not ask for confirmation', default=False)
# edit
p = sub.add_parser('edit', help='edit the reference texnote')
p.add_argument('-v', '--view', action='store_true',
help='open the paper in a pdf viewer', default=False)
p.add_argument('-w', '--with', dest='with_command', default=None,
help='command to use to open the file, default is the main config one. You can set one in the texnote config section')
add_references_argument(p, single=True)
# edit_template
p = sub.add_parser('edit_template',
help='edit the latex template used by texnote')
p.add_argument('-w', '--with', dest='with_command', default=None,
help='command to use to open the file, default is the main config one. You can set one in the texnote config section')
p.add_argument('-B', '--body', action='store_true',
help='edit the main body', default=False)
p.add_argument('-S', '--style', action='store_true',
help='open the style', default=False)
# generate_bib
p = sub.add_parser('generate_bib',
help='generate the latex bib used by texnote')
# clean
p = sub.add_parser('clean',
help='delete all but tex files and pdf document in the texnote folder')
p.add_argument('-f', '--force', action='store_true',
help='do not ask for confirmation', default=False)
p.add_argument('-d', '--deep', action='store_true',
help='also delete tex file and pdf document that are not associated to a paper', default=False)
p.add_argument('-p', '--pdf', action='store_true',
help='also delete all pdf document', default=False)
# generate_pdf
p = sub.add_parser('generate_pdf',
help='compile a texnote from its reference')
add_references_argument(p, single=True)
p.add_argument('-o', '--open', action='store_true', dest='open_pdf',
default=False, help='open the resulting pdf')
p.add_argument('-w', '--with', dest='with_command', default=None,
help='command to use to open the pdf, default is the main config one')
p.add_argument('-C', '--noclean', action='store_false', dest='clean',
default=True, help="don't clean document afterwards")
p.add_argument('-v', '--verbose', action='store_true', dest='verbose',
default=False, help="display stdout")
# extract_note
p = sub.add_parser('extract_note',
help='extract core note from its reference')
add_references_argument(p, single=True)
return [(self.name, self.command)]
def command(self, args):
self._ensure_init()
texcmd = args.texcmd
del args.texcmd
self.texcmds[texcmd](**vars(args))
def _texfile(self, citekey):
return os.path.join(DIR, citekey + '.tex')
def _exist_texfile(self, citekey):
return files.check_file(self._texfile(citekey))
def _ensure_texfile(self, citekey):
if not self._exist_texfile(citekey):
shutil.copy(TPL_BODY, self._texfile(citekey))
def get_bib_style(self):
default = DFT_BIBSTYLE_INFO
return config(SECTION).get('bib_style', default)
def _autofill_texfile(self, citekey):
with open(self._texfile(citekey)) as f:
text = f.read()
rp = repo.Repository(config())
if citekey in rp:
paper = rp.get_paper(citekey)
text = autofill(text, paper)
text = replace_pattern(text, STYLE_PATTERN, STYLE_INFO)
text = replace_pattern(text, BIB_PATTERN, BIB_INFO)
text = replace_pattern(text, BIBSTYLE_PATTERN, self.get_bib_style())
with open(self._texfile(citekey), "w") as f:
f.write(text)
def get_texfile(self, citekey, autofill=False):
""" This function returns the name of the texfile and
ensure it exist and it is filled with info from the bibfile if possible"""
self._ensure_texfile(citekey)
if autofill:
self._autofill_texfile(citekey)
return self._texfile(citekey)
def get_edit_cmd(self):
default = config().edit_cmd
return config(SECTION).get('edit_cmd', default)
def edit(self, reference, view=False, with_command=None):
if view:
subprocess.Popen(['papers', 'open', reference])
if with_command is None:
with_command = self.get_edit_cmd()
rp = repo.Repository(config())
citekey = parse_reference(rp, reference)
files.edit_file(with_command,
self.get_texfile(citekey, autofill=True),
temporary=False)
def edit_template(self, body=False, style=False, with_command=None):
if with_command is None:
with_command = self.get_edit_cmd()
if body:
files.edit_file(with_command, TPL_BODY, temporary=False)
if style:
files.edit_file(with_command, TPL_STYLE, temporary=False)
def remove(self, reference, force=False):
rp = repo.Repository(config())
citekey = parse_reference(rp, reference)
if not force:
ui = get_ui()
are_you_sure = 'Are you sure you want to delete [{}]'.format(citekey)
sure = ui.input_yn(question=are_you_sure, default='n')
if force or sure:
os.remove(self.get_texfile(citekey))
def rename(self, old_citekey, new_citekey, overwrite=False):
if self._exist_texfile(old_citekey):
if not overwrite and self._exist_texfile(new_citekey):
ui = get_ui()
are_you_sure = 'Are you sure you want to delete [{}]'.format(citekey)
sure = ui.input_yn(question=are_you_sure, default='n')
if overwrite or sure:
shutil.move(self.get_texfile(old_citekey), self.get_texfile(new_citekey))
def generate_bib(self):
if files.check_file(TPL_BIB):
os.remove(TPL_BIB)
cmd = 'papers list -k |xargs papers export >> {}'.format(TPL_BIB)
os.system(cmd)
def clean(self, force=False, deep=False, pdf=False):
if deep:
rp = repo.Repository(config())
to_keep = ['.tex']
if not pdf:
to_keep.append('.pdf')
for f in os.listdir(DIR):
path = os.path.join(DIR, f)
if os.path.isfile(path):
name, extension = os.path.splitext(path)
if extension in to_keep:
if not deep:
continue
citekey, _ = os.path.splitext(f)
if citekey in rp:
continue
if not force:
ui = get_ui()
are_you_sure = 'Are you sure you want to delete file [{}]'.format(path)
sure = ui.input_yn(question=are_you_sure, default='n')
if force or sure:
os.remove(path)
def generate_pdf(self, reference, open_pdf=False,
with_command=None, clean=True, verbose=False):
rp = repo.Repository(config())
citekey = parse_reference(rp, reference)
path = self.get_texfile(citekey, autofill=True)
latex_tools.full_compile(path, verbose)
if clean:
self.clean(force=True)
if open_pdf:
if with_command is None:
with_command = config().open_cmd
cmd = with_command.split()
cmd.append(os.path.splitext(path)[0] + '.pdf')
subprocess.Popen(cmd)
def extract_note(self, reference):
rp = repo.Repository(config())
citekey = parse_reference(rp, reference)
path = self.get_texfile(citekey, autofill=True)
with open(path) as f:
text = f.read()
print latex_tools.extract_note(text)
@RemoveEvent.listen()
def remove(rmevent):
texplug = TexnotePlugin.get_instance()
texplug.remove(rmevent.citekey, force=True)
@RenameEvent.listen()
def rename(renamevent):
texplug = TexnotePlugin.get_instance()
texplug.rename(renamevent.old_citekey,
renamevent.paper.citekey,
overwrite=True)