Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Denite source #19

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 0 additions & 15 deletions python/citation_vim/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os.path
import string
import pickle
from citation_vim.utils import raiseError
from citation_vim.item import Item

Expand Down Expand Up @@ -106,20 +105,6 @@ def get_parser(self):
parser = ZoteroParser(self.context)
return parser

def read_cache(self):
"""
Returns items from the cache file.
"""
with open(self.cache_file, 'rb') as in_file:
return pickle.load(in_file)

def write_cache(self, items):
"""
Writes the cache file.
"""
with open(self.cache_file, 'wb') as out_file:
pickle.dump(items, out_file)

def is_cached(self):
"""
Returns boolean based on cache and target file dates
Expand Down
15 changes: 15 additions & 0 deletions python/citation_vim/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re
import os.path
from datetime import datetime, timedelta
import pickle

def compat_str(string):
if sys.version_info[0] == 2:
Expand Down Expand Up @@ -36,3 +37,17 @@ def raiseError(message):

def strip_braces(string):
return re.sub("[{.*}]+", "", string)

def read_cache(cache_file):
"""
Returns items from the cache file.
"""
with open(cache_file, 'rb') as in_file:
return pickle.load(in_file)

def write_cache(cache_file, items):
"""
Writes the cache file.
"""
with open(cache_file, 'wb') as out_file:
pickle.dump(items, out_file)
43 changes: 43 additions & 0 deletions rplugin/python3/denite/kind/citation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import os
import re
from .word import Kind as Word
from .command import Kind as Command
from .file import Kind as File
from .directory import Kind as Directory


class Kind(Word, Command, File, Directory):

def __init__(self, vim):
super().__init__(vim)

self.name = 'citation'
self.default_action = 'default'
# self.persist_actions = ['preview']

def action_default(self, context):
target = context['targets'][0]
source_context = target['source_context']

if source_context['__source'] is 'sub_sources':
self.action_field(context)
else:
Word.action_append(self, context)

def action_field(self, context):
target = context['targets'][0]
cmd = 'Denite citation:{}'.format(target['action__source_field'])
self.vim.command(cmd)

def action_open(self, context):
for target in context['targets']:
path = target['action__path']
self.vim.call('denite#util#open', path)

def action_directory(self, context):
Directory.action_open(self, context)

def action_preview(self, context):
target = context['targets'][0]
if 'action__command' in target:
Command.action_execute(self, context)
228 changes: 228 additions & 0 deletions rplugin/python3/denite/source/citation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import sys
from os.path import abspath, join, pardir
from .base import Base

sys.path.append(
abspath(join(__file__, pardir, pardir, pardir, pardir, pardir, 'python')))
from citation_vim.utils import read_cache, write_cache, is_current, raiseError
from citation_vim.item import Item

sub_sources = [
"abstract",
"author",
"collection",
"combined",
"date",
"doi",
"duplicate_keys",
"file",
"isbn",
"publication",
"key",
"key_inner",
"language",
"issue",
"notes",
"pages",
"publisher",
"tags",
"title",
"type",
"url",
"volume",
"zotero_key"
]

key_title_banned_regex = r"\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l|el|las|los|al|uno|una|unos|unas|de|des|del|d)\W"
key_clean_regex = "[^A-Za-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+"


class Source(Base):
""" Zotero/Bibtex source for Denite.nvim """

def __init__(self, vim):
super().__init__(vim)

self.name = 'citation'
self.kind = 'citation'
self.matchers = ['matcher_fuzzy']
self.is_public_context = True

self.sub_sources = sub_sources
self.__cache = False
self.__cache_file = None
self._parser = None

self.vars = {
'cache_path': "",
'mode': 'zotero',
'zotero_version': 5,
'zotero_path': '~/Zotero',
'zotero_attachment_path': '~/Zotero/library',
'collection': "",
'bibtex_file': "",
'reverse_order': True,
'et_al_limit': 5,
'key_clean_regex': key_clean_regex,
'key_title_banned_regex': key_title_banned_regex,
'key_format': "",
'key_outer_prefix': '[',
'key_inner_prefix': '@',
'key_suffix': ']',
'desc_format': '{}∶ {} ‴{}‴ ₋{}₋ ₍{}₎',
'desc_fields': ["type", "key", "title", "author", "date"],
'wrap_chars': '||',
'highlight_dash': "‾⁻−₋‐⋯┄–—―∼┈─▭▬┉━┅₌⁼‗",
'highlight_bar': "‖│┃┆∥┇┊┋",
'highlight_bracket': "⊂〔₍⁽⊃〕₎⁾",
'highlight_arrow': "◀◁<‹▶▷>›",
'highlight_colon': "∶∷→⇒≫",
'highlight_blob': "♯♡◆◇◊○◎●◐◑∗∙⊙⊚⌂★☺☻▪■□▢▣▤▥▦▧▨▩",
'highlight_tiny': "、。‸₊⁺∘♢☆☜☞♢☼",
'highlight_text': "″‴‶‷",
'searchkeys': [],
}

def on_init(self, context):
if len(context['args']) >= 1:
context['__source'] = 'source_field'
context['__field'] = context['args'].pop(0)

# Set mode; zotero or bibtex
self._set_mode(context)
else:
context['__source'] = 'sub_sources'

def gather_candidates(self, context):
if context['__source'] is 'sub_sources':
return self._gather_sub_sources()
else:
return self._gather_items(context)

def _set_mode(self, context):
""" Set up bibtex or zotero mode """
if self.vars['mode'] == "bibtex" and self.vars['bibtex_file']:
# Enable cache
self._enable_cache()
# Get parser
from citation_vim.bibtex.parser import BibtexParser
self._parser = BibtexParser(self.vars)
elif self.vars['mode'] == "zotero" and self.vars['zotero_path']:
# Check if searchkeys are given and set cache mode accordingly.
self._get_searchkeys(context)
# Get parser
from citation_vim.zotero.parser import ZoteroParser
self.vars['zotero_version'] = int(self.vars['zotero_version'])
self._parser = ZoteroParser(self.vars)
else:
raiseError("'mode' must be set to 'zotero' or 'bibtex'")

def _enable_cache(self):
self.__cache = True
self.__cache_file = join(self.vars['cache_path'], "citation_vim_cache")

def _get_searchkeys(self, context):
if len(context['args']) > 0:
self.vars['searchkeys'] = context['args'].pop(0)
self.__cache = False
else:
self.vars['searchkeys'] = []
self._enable_cache()

def _gather_sub_sources(self):
# Generate candidates and return it
candidates = []
for sub_source in self.sub_sources:
candidates.append({
"word": sub_source,
"action__source_field": sub_source,
})
return candidates

def _gather_items(self, context):
candidates = []

if context['__field'] is 'duplicate_keys':
items = self._get_duplicate_key(context)
else:
items = self._get_items(context)

if context['__field'] is 'key':
text = (self.vars['key_outer_prefix']
+ self.vars['key_inner_prefix']
+ '{}'
+ self.vars['key_suffix'])
elif context['__field'] is 'key_inner':
text = self.vars['key_inner_prefix'] + '{}'
else:
text = '{}'

if context['__field'] is 'url':
file_url = 'url'
else:
file_url = 'file'

# Update vars with source field
self.vars['source_field'] = context['__field']

# Retirn items
for item in items:
if (not self.vars['collection']
or self.vars['collection'] in item.collections):
candidate = {
"word": item.describe(self.vars),
"action__text": text.format(getattr(item, context['__field'])),
"action__path": getattr(item, file_url),
"action__command": self._set_message(item.combined),
}
candidates.append(candidate)
return candidates

def _set_message(self, message):
return "echo {}".format(message)

def _get_duplicate_keys(self, context):
"""
Returns an array of collections.
"""
self.vars['collection'] = ""
context['__field'] = 'key'
self.__cache = False

# Get items
items = self._get_items(context)

# Filter itesm for duplicate keys
items.sort(key=lambda item: item.key)
last_item = Item()
last_item.key = ""
filtered_items = []
for item in items:
if last_item.key == item.key:
filtered_items.append(item)
last_item = item
return filtered_items

def _get_items(self, context):
"""
Returns items from cache or parser
"""
if self.__cache and self._is_cached():
return read_cache(self.__cache_file)
items = self._parser.load()
if self.vars['reverse_order']:
items.reverse()
if self.__cache:
write_cache(self.__cache_file, items)
return items

def _is_cached(self):
"""
Returns boolean based on cache and target file dates
"""
if self.vars['mode'] == 'bibtex':
file_path = self.vars['bibtex_file']
elif self.vars['mode'] == 'zotero':
zotero_database = join(self.vars['zotero_path'], "zotero.sqlite")
file_path = zotero_database
return is_current(file_path, self.__cache_file)
36 changes: 36 additions & 0 deletions rplugin/python3/denite/source/citation_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from os.path import dirname
from .citation import Source as Base


class Source(Base):

def __init__(self, vim):
super().__init__(vim)

self.name = 'citation_collection'
self.description = "search citation collection"
self.kind = 'command'

def gather_candidates(self, context):
"""
Returns an array of collections.
"""
candidates = {}
collections = {}
for item in self._get_items(context):
for col in item.collections:
if not col in collections:
collections[col] = col

candidates.append({
"word": col,
"action__command": self._set_col(col),
# "action__type": ": ",
"action__text": col,
"action__path": col,
"action__directory": dirname(col),
})
return candidates

def _set_collection(self, collection):
return "call denite#custom#var('citation', 'collection', '{}')".format(collection)