unity-scope-devhelp-0.1+14.04.20140328/0000755000015201777760000000000012315237117017660 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/0000755000015201777760000000000012315237117021022 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/__init__.py0000644000015201777760000000000012315236730023121 0ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/fake-devhelp.py0000755000015201777760000000010412315236730023725 0ustar pbusernogroup00000000000000#!/usr/bin/python3 # -*- coding: utf-8 -*- import sys sys.exit(1) unity-scope-devhelp-0.1+14.04.20140328/tests/test_devhelp.py0000644000015201777760000000452112315236730024064 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 TestDevhelp(ScopeTestCase): def setUp(self): self.init_scope('src/unity_devhelp_daemon.py') def tearDown(self): self.scope = None self.scope_module = None def test_search(self): self.scope_module.HELP_LOCATION = 'tests/data/test_devhelp_pass/' expected_results = ["A sample property", "A sample property"] results = [] for s in ['property']: 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_failing_search(self): self.scope_module.HELP_LOCATION = 'tests/data/test_devhelp_fail/' for s in ['upnriitnyt']: result_set = self.perform_query(s) self.assertEqual(len(result_set.results), 0) def test_activation(self): result = Unity.ScopeResult() result.uri = "tests/data/C/sample_help/mock_devhelp_file" self.scope_module.DEVHELP_COMMAND = 'tests/fake-devhelp.py' activation = self.scope.activate(result, Unity.SearchMetadata(), None) self.assertEqual(activation.props.goto_uri, None) self.assertEqual(activation.props.handled, Unity.HandledType.HIDE_DASH) if __name__ == '__main__': unittest.main() unity-scope-devhelp-0.1+14.04.20140328/tests/data/0000755000015201777760000000000012315237117021733 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_pass/0000755000015201777760000000000012315237117025447 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_pass/test_devhelp_docs/0000755000015201777760000000000012315237117031145 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_pass/test_devhelp_docs/test_devhelp_docs.devhelp2unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_pass/test_devhelp_docs/test_devhelp_d0000644000015201777760000000116212315236730034061 0ustar pbusernogroup00000000000000 unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_fail/0000755000015201777760000000000012315237117025414 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_fail/test_devhelp_docs/0000755000015201777760000000000012315237117031112 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_fail/test_devhelp_docs/test_devhelp_docs.devhelp2unity-scope-devhelp-0.1+14.04.20140328/tests/data/test_devhelp_fail/test_devhelp_docs/test_devhelp_d0000644000015201777760000000115212315236730034025 0ustar pbusernogroup00000000000000 unity-scope-devhelp-0.1+14.04.20140328/setup.py0000644000015201777760000000157012315236730021375 0ustar pbusernogroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Setup file for devhelp dash plugin ''' from distutils.core import setup from DistUtilsExtra.command import build_extra from DistUtilsExtra.command import build_i18n setup(name='unity-scope-devhelp', 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-devhelp.service']), #('share/icons/unity-icon-theme/places/svg', ['data/icons/service-devhelp.svg']), ('share/unity-scopes/devhelp', ['src/unity_devhelp_daemon.py']), ('share/unity-scopes/devhelp', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n, }) unity-scope-devhelp-0.1+14.04.20140328/setup.cfg0000644000015201777760000000020312315236730021474 0ustar pbusernogroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-devhelp desktop_files=[('share/unity/scopes/code', ('data/devhelp.scope.in',))] unity-scope-devhelp-0.1+14.04.20140328/po/0000755000015201777760000000000012315237117020276 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/po/POTFILES.in0000644000015201777760000000012712315236730022053 0ustar pbusernogroup00000000000000[encoding: UTF-8] src/unity_devhelp_daemon.py [type: gettext/ini]data/devhelp.scope.in unity-scope-devhelp-0.1+14.04.20140328/po/unity-scope-devhelp.pot0000644000015201777760000000211412315236730024724 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_devhelp_daemon.py:36 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-02-25 14:56+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_devhelp_daemon.py:34 ../data/devhelp.scope.in.h:4 msgid "Search Devhelp" msgstr "" #: ../src/unity_devhelp_daemon.py:35 msgid "Sorry, there are no Devhelp results that match your search." msgstr "" #: ../src/unity_devhelp_daemon.py:45 msgid "Technical Documents" msgstr "" #: ../data/devhelp.scope.in.h:1 msgid "devhelp;" msgstr "" #: ../data/devhelp.scope.in.h:2 msgid "Devhelp" msgstr "" #: ../data/devhelp.scope.in.h:3 msgid "Find Devhelp items" msgstr "" unity-scope-devhelp-0.1+14.04.20140328/MANIFEST.in0000644000015201777760000000007612315236730021421 0ustar pbusernogroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-devhelp-0.1+14.04.20140328/src/0000755000015201777760000000000012315237117020447 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/src/__init__.py0000644000015201777760000000000012315236730022546 0ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/src/unity_devhelp_daemon.py0000644000015201777760000002305412315236743025233 0ustar pbusernogroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- # Copyright(C) 2013 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 os.path import gzip import subprocess from xml.dom import minidom import lxml.html import re APP_NAME = 'unity-scope-devhelp' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Developer.Devhelp' UNIQUE_PATH = '/com/canonical/unity/scope/developer/devhelp' SEARCH_HINT = _('Search Devhelp') NO_RESULTS_HINT = _('Sorry, there are no Devhelp results that match your search.') PROVIDER_CREDITS = _('') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR + 'service-firefoxbookmarks.svg' DEFAULT_RESULT_ICON = SVG_DIR + 'result-help.svg' DEFAULT_RESULT_MIMETYPE = 'text/html' DEFAULT_RESULT_TYPE = Unity.ResultType.DEFAULT HELP_LOCATION = "/usr/share/gtk-doc/html/" DEVHELP_COMMAND = 'devhelp' c1 = {'id': 'documentation', 'name': _('Technical Documents'), 'icon': SVG_DIR + 'group-installed.svg', 'renderer': Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1] FILTERS = [] EXTRA_METADATA = [] CACHE_DEVHELP = None def setup_devhelp(): ''' Parses local devhelp index files for tags and associates them with the page's uri in self.data as: {name, link, type, source title} ''' data = [] for dirname in os.listdir(HELP_LOCATION): directory = HELP_LOCATION + dirname for filename in os.listdir(directory): filename = directory + "/" + filename if filename.endswith("devhelp2"): book = "" xmldoc = minidom.parse(filename) nodes = xmldoc.getElementsByTagName('book') for node in nodes: book = node.getAttribute('title') nodes = xmldoc.getElementsByTagName('keyword') for node in nodes: record = [] record.append(node.getAttribute('name')) record.append(directory + '/' + node.getAttribute('link')) record.append(node.getAttribute('type')) record.append(book) data.append(record) if filename.endswith("devhelp2.gz"): book = "" f = gzip.open(filename, 'rb') xmldoc = minidom.parse(f) nodes = xmldoc.getElementsByTagName('book') for node in nodes: book = node.getAttribute('title') nodes = xmldoc.getElementsByTagName('keyword') for node in nodes: record = [] record.append(node.getAttribute('name')) record.append(directory + '/' + node.getAttribute('link')) record.append(node.getAttribute('type')) record.append(book) data.append(record) return data def search(search, filters): ''' Search for help documents matching the search string ''' results = [] if len(search) < 2: return results global CACHE_DEVHELP if not CACHE_DEVHELP: print("Loading results...") devhelp = setup_devhelp() CACHE_DEVHELP = devhelp else: devhelp = CACHE_DEVHELP icon_hint = Gio.ThemedIcon.new("text-x-generic").to_string() for data in devhelp: if search.lower() in data[0].lower(): if len(results) < 50: results.append({'uri': data[0], 'icon': icon_hint, 'category': 0, 'title': data[0], 'comment': data[3], 'dnd_uri': data[1]}) return results class Preview(Unity.ResultPreviewer): def do_run(self): preview = Unity.GenericPreview.new(self.result.title, '', None) preview.props.subtitle = self.result.comment preview.props.image = Gio.ThemedIcon.new(self.result.icon_hint) description = self.result.dnd_uri match = re.search('#', self.result.dnd_uri) f = open(self.result.dnd_uri[:match.start()]) f = f.read() path = lxml.html.fromstring(f) anchor = self.result.dnd_uri[match.end():] anchorpath = path.xpath("//a[@name='%s']" % anchor)[0] parent = anchorpath.getparent() description = parent.text_content() lines = description.split('\n') description = '' for line in lines: if self.result.title in line: line = line[len(self.result.title):] elif line.endswith(':'): line = '\n \n%s\n\t' % line elif ' : ' in line: line = '%s\n \n' % line elif line.endswith(';'): line = '%s\n \n' % line elif line.startswith('Since'): line = '\n \n%s\n' % line else: line = '%s ' % line description = description + line while ' ' in description: description = description.replace(' ', ' ') while '\n\n' in description: description = description.replace('\n\n', '\n') if len(description) > 5000: description = description[:5000] + '…' preview.props.description_markup = description view_action = Unity.PreviewAction.new("show", _("Show"), None) preview.add_action(view_action) return preview # 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 do_activate(self, result, metadata, id): uri = result.uri[:len(result.uri) - 3] parameters = [DEVHELP_COMMAND, "-s", uri] subprocess.Popen(parameters) return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri=None) def do_create_previewer(self, result, metadata): rp = Preview() rp.set_scope_result(result) rp.set_search_metadata(metadata) return rp def load_scope(): return Scope() unity-scope-devhelp-0.1+14.04.20140328/data/0000755000015201777760000000000012315237117020571 5ustar pbusernogroup00000000000000unity-scope-devhelp-0.1+14.04.20140328/data/devhelp.scope.in0000644000015201777760000000131312315236743023662 0ustar pbusernogroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Developer.Devhelp DBusPath=/com/canonical/unity/scope/developer/devhelp Icon= QueryBinary=devhelp _Keywords=devhelp;dev;help;doc; RequiredMetadata= OptionalMetadata= Loader=/usr/share/unity-scopes/devhelp/unity_devhelp_daemon.py Module=devhelp.unity_devhelp_daemon ModuleType=python3 RemoteContent=false Type=code Master=code.scope _Name=Devhelp _Description=This is an Ubuntu search plugin that enables information from Devhelp to be searched and displayed in the Dash underneath the Code header. If you do not wish to search this content source, you can disable this search plugin. _SearchHint=Search Devhelp [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-devhelp unity-scope-devhelp-0.1+14.04.20140328/data/unity-scope-devhelp.service0000644000015201777760000000023212315236730026054 0ustar pbusernogroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Developer.Devhelp Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s code/devhelp.scope unity-scope-devhelp-0.1+14.04.20140328/data/icons/0000755000015201777760000000000012315237117021704 5ustar pbusernogroup00000000000000