unity-scope-texdoc-0.1+14.04.20140328/0000755000015201777760000000000012315236707017523 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/tests/0000755000015201777760000000000012315236707020665 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/tests/__init__.py0000644000015201777760000000000012315236501022754 0ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/tests/test_texdoc.py0000644000015201777760000000352312315236501023557 0ustar pbusernogroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- from gi.repository import Unity from unittest import TestCase import imp class ResultSet(Unity.ResultSet): def __init__(self): Unity.ResultSet.__init__(self) self.results = [] def do_add_result(self, result): self.results.append({'uri':result.uri, 'title':result.title, 'comment':result.comment, 'icon':result.icon_hint}) class ScopeTestCase(TestCase): def init_scope(self, scope_path): self.scope_module = imp.load_source('scope', scope_path) self.scope = self.scope_module.load_scope() def perform_query(self, query, filter_set = Unity.FilterSet.new()): result_set = ResultSet() ctx = Unity.SearchContext.create(query, 0, filter_set, None, result_set, None) s = self.scope.create_search_for_query(ctx) s.run() return result_set class TestAskUbuntu(ScopeTestCase): def setUp(self): self.init_scope('src/unity_texdoc_daemon.py') def tearDown(self): self.scope = None self.scope_module = None def test_questions_search(self): expected_results = ["file:///usr/share/texlive/texmf-dist/doc/texdoc/texdoc.pdf", "texdoc.pdf"] results = [] for s in ['texdoc']: result_set = self.perform_query(s) results.append(result_set.results[0]['uri']) results.append(result_set.results[0]['title']) self.assertEqual(results, expected_results) def test_questions_failing_search(self): for s in ['upnriitnyt']: result_set = self.perform_query(s) self.assertEqual(len(result_set.results), 0) if __name__ == '__main__': unittest.main() unity-scope-texdoc-0.1+14.04.20140328/tests/data/0000755000015201777760000000000012315236707021576 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/tests/data/mock_texdoc_fail0000644000015201777760000000000612315236501024777 0ustar pbusernogroup00000000000000 unity-scope-texdoc-0.1+14.04.20140328/tests/data/mock_texdoc_pass0000644000015201777760000000000012315236501025024 0ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/setup.py0000644000015201777760000000156112315236501021230 0ustar pbusernogroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Setup file for texdoc dash plugin ''' from distutils.core import setup from DistUtilsExtra.command import build_extra from DistUtilsExtra.command import build_i18n setup(name='unity-scope-texdoc', version='0.1', author='Mark Tully', author_email='markjtully@gmail.com', url='http://launchpad.net/ubuntu-scopes', license='GNU General Public License (GPL)', data_files=[('share/dbus-1/services', ['data/unity-scope-texdoc.service']), # ('share/icons/unity-icon-theme/places/svg', ['data/icons/service-texdoc.svg']), ('share/unity-scopes/texdoc', ['src/unity_texdoc_daemon.py']), ('share/unity-scopes/texdoc', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n, }) unity-scope-texdoc-0.1+14.04.20140328/setup.cfg0000644000015201777760000000020112315236501021325 0ustar pbusernogroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-texdoc desktop_files=[('share/unity/scopes/help', ('data/texdoc.scope.in',))] unity-scope-texdoc-0.1+14.04.20140328/po/0000755000015201777760000000000012315236707020141 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/po/POTFILES.in0000644000015201777760000000012512315236501021704 0ustar pbusernogroup00000000000000[encoding: UTF-8] src/unity_texdoc_daemon.py [type: gettext/ini]data/texdoc.scope.in unity-scope-texdoc-0.1+14.04.20140328/po/unity-scope-texdoc.pot0000644000015201777760000000207712315236501024426 0ustar pbusernogroup00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #: ../src/unity_texdoc_daemon.py:45 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-02-25 23:57+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/unity_texdoc_daemon.py:43 ../data/texdoc.scope.in.h:4 msgid "Search Texdoc" msgstr "" #: ../src/unity_texdoc_daemon.py:44 msgid "Sorry, there are no Texdoc results that match your search." msgstr "" #: ../src/unity_texdoc_daemon.py:54 msgid "Technical Documents" msgstr "" #: ../data/texdoc.scope.in.h:1 msgid "texdoc;" msgstr "" #: ../data/texdoc.scope.in.h:2 msgid "Texdoc" msgstr "" #: ../data/texdoc.scope.in.h:3 msgid "Find Texdoc items" msgstr "" unity-scope-texdoc-0.1+14.04.20140328/MANIFEST.in0000644000015201777760000000007612315236501021254 0ustar pbusernogroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-texdoc-0.1+14.04.20140328/src/0000755000015201777760000000000012315236707020312 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/src/__init__.py0000644000015201777760000000000012315236501022401 0ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/src/unity_texdoc_daemon.py0000644000015201777760000002002512315236512024716 0ustar pbusernogroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- # Copyright(C) 2012 Frederik Elwert # 2012 Pawel Stolowski # 2012 Mark Tully # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . from gi.repository import GLib, Gio from gi.repository import Unity import gettext import re import os.path from subprocess import Popen, PIPE from mimetypes import guess_type from html.parser import HTMLParser try: from pyPdf import PdfFileReader from pyPdf.utils import PdfReadError PDF_AVAILABLE = True except ImportError: PDF_AVAILABLE = False APP_NAME = 'unity-scope-texdoc' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Help.Texdoc' UNIQUE_PATH = '/com/canonical/unity/scope/help/texdoc' SEARCH_HINT = _('Search Texdoc') NO_RESULTS_HINT = _('Sorry, there are no Texdoc results that match your search.') PROVIDER_CREDITS = _('') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR + 'service-texdoc.svg' DEFAULT_RESULT_ICON = SVG_DIR + 'result-help.svg' DEFAULT_RESULT_MIMETYPE = 'text/html' DEFAULT_RESULT_TYPE = Unity.ResultType.DEFAULT TEXDOC_RE = re.compile('^\s*(\d+)\s+(.+?)$') c1 = {'id': 'help', 'name': _('Technical Documents'), 'icon': SVG_DIR + 'group-installed.svg', 'renderer': Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1] FILTERS = [] EXTRA_METADATA = [] def get_file_info(filepath): info = {} info['uri'] = 'file://' + filepath info['filename'] = os.path.basename(filepath) info['mimetype'] = guess_type(info['uri'])[0] or '' if info['mimetype']: info['icon'] = Gio.content_type_get_icon(info['mimetype']) if info['mimetype'] == 'application/pdf' and PDF_AVAILABLE: info['title'] = get_pdf_title(filepath) elif info['mimetype'] == 'text/html': info['title'] = get_html_title(filepath) else: info['title'] = '' else: info['icon'] = Gio.ThemedIcon.new('text-x-generic') info['title'] = '' return info def get_pdf_title(filepath): with open(filepath, 'rb') as pdffile: reader = PdfFileReader(pdffile) try: return reader.documentInfo.title or '' except PdfReadError: return '' def get_html_title(filepath): class HTMLTitleParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.is_title = False self.title_complete = False self.title = '' def handle_starttag(self, tag, attrs): if tag == 'title': self.is_title = True def handle_data(self, data): if self.is_title: self.title += data def handle_endtag(self, tag): if tag == 'title': self.title_complete = True self.is_title = False with open(filepath, 'r') as htmlfile: parser = HTMLTitleParser() for line in htmlfile: parser.feed(line) if parser.title_complete: return parser.title def search(search, filters): ''' Search for help documents matching the search string ''' results = [] result = [] if len(search) > 2: # don't run texdoc for strings shorter than 3 chars proc = Popen(["texdoc", "--list", "--nointeract", search], stdout=PIPE) os.waitpid(proc.pid, 0) out = proc.communicate()[0] out = out.decode('utf8') for line in out.splitlines(): m = TEXDOC_RE.match(line) if m: result.append(m.group(2)) for res in result: info = get_file_info(res) if info['mimetype']: # Only handle known file types, otherwise we might get # Makefiles and things like that. results.append({'uri': info['uri'], 'icon': info['icon'].to_string(), 'category': 0, 'mimetype': info['mimetype'], 'title': info['filename'], 'comment': info['title']}) return results def activate(scope, uri): ''' Open the url in the default webbrowser Args: uri: The url to be opened ''' uri = uri[:len(uri) - 3] parameters = ["devhelp", "-s", uri] subprocess.Popen(parameters) return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri='') # Classes below this point establish communication # with Unity, you probably shouldn't modify them. class MySearch(Unity.ScopeSearchBase): def __init__(self, search_context): super(MySearch, self).__init__() self.set_search_context(search_context) def do_run(self): ''' Adds results to the model ''' try: result_set = self.search_context.result_set for i in search(self.search_context.search_query, self.search_context.filter_state): if not 'uri' in i or not i['uri'] or i['uri'] == '': continue if not 'icon' in i or not i['icon'] or i['icon'] == '': i['icon'] = DEFAULT_RESULT_ICON if not 'mimetype' in i or not i['mimetype'] or i['mimetype'] == '': i['mimetype'] = DEFAULT_RESULT_MIMETYPE if not 'result_type' in i or not i['result_type'] or i['result_type'] == '': i['result_type'] = DEFAULT_RESULT_TYPE if not 'category' in i or not i['category'] or i['category'] == '': i['category'] = 0 if not 'title' in i or not i['title']: i['title'] = '' if not 'comment' in i or not i['comment']: i['comment'] = '' if not 'dnd_uri' in i or not i['dnd_uri'] or i['dnd_uri'] == '': i['dnd_uri'] = i['uri'] result_set.add_result(**i) except Exception as error: print(error) class Scope(Unity.AbstractScope): def __init__(self): Unity.AbstractScope.__init__(self) def do_get_search_hint(self): return SEARCH_HINT def do_get_schema(self): ''' Adds specific metadata fields ''' schema = Unity.Schema.new() if EXTRA_METADATA: for m in EXTRA_METADATA: schema.add_field(m['id'], m['type'], m['field']) #FIXME should be REQUIRED for credits schema.add_field('provider_credits', 's', Unity.SchemaFieldType.OPTIONAL) return schema def do_get_categories(self): ''' Adds categories ''' cs = Unity.CategorySet.new() if CATEGORIES: for c in CATEGORIES: cat = Unity.Category.new(c['id'], c['name'], Gio.ThemedIcon.new(c['icon']), c['renderer']) cs.add(cat) return cs def do_get_filters(self): ''' Adds filters ''' fs = Unity.FilterSet.new() #if FILTERS: # return fs def do_get_group_name(self): return GROUP_NAME def do_get_unique_name(self): return UNIQUE_PATH def do_create_search_for_query(self, search_context): se = MySearch(search_context) return se def load_scope(): return Scope() unity-scope-texdoc-0.1+14.04.20140328/data/0000755000015201777760000000000012315236707020434 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/data/texdoc.scope.in0000644000015201777760000000111712315236512023354 0ustar pbusernogroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Help.Texdoc DBusPath=/com/canonical/unity/scope/help/texdoc Icon= QueryBinary=texdoc Module=texdoc.unity_texdoc_daemon ModuleType=python3 _Keywords=texdoc;tex;latex; RequiredMetadata= OptionalMetadata= Type=help _Name=TeXdoc _Description=This is an Ubuntu search plugin that enables information from TeXdoc to be searched and displayed in the Dash underneath the Help header. If you do not wish to search this content source, you can disable this search plugin. _SearchHint=Search Texdoc [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-texdoc unity-scope-texdoc-0.1+14.04.20140328/data/icons/0000755000015201777760000000000012315236707021547 5ustar pbusernogroup00000000000000unity-scope-texdoc-0.1+14.04.20140328/data/unity-scope-texdoc.service0000644000015201777760000000022312315236501025546 0ustar pbusernogroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Help.Texdoc Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s help/texdoc.scope