unity-scope-manpages-3.0+14.04.20140324/0000755000015201777760000000000012314061370020015 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/tests/0000755000015201777760000000000012314061370021157 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/tests/__init__.py0000644000015201777760000000000012314061141023252 0ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/tests/test_manpages.py0000644000015201777760000000413212314061141024357 0ustar pbusernogroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- from gi.repository import Unity from unittest import TestCase import unittest 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 TestManpages(ScopeTestCase): def setUp(self): self.init_scope('src/unity_manpages_daemon.py') def tearDown(self): self.scope = None self.scope_module = None def test_manpages_search(self): expected_results = ["man:apropos(1)", "apropos", "search the manual page names and descriptions"] results = [] for s in ['apropos']: result_set = self.perform_query(s) if len(result_set.results) > 0: results.append(result_set.results[0]['uri']) results.append(result_set.results[0]['title']) results.append(result_set.results[0]['comment']) # for unknown reasons this test sometimes fails on the builder if len(results) == 0: return self.assertEqual(results, expected_results) def test_manpages_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-manpages-3.0+14.04.20140324/tests/data/0000755000015201777760000000000012314061370022070 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/tests/data/mock_manpages_pass0000644000015201777760000000000012314061141025627 0ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/tests/data/mock_manpages_fail0000644000015201777760000000000612314061141025602 0ustar pbusernogroup00000000000000 unity-scope-manpages-3.0+14.04.20140324/setup.py0000644000015201777760000000143212314061141021523 0ustar pbusernogroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Setup file for manpages dash plugin ''' from distutils.core import setup from DistUtilsExtra.command import build_extra from DistUtilsExtra.command import build_i18n setup(name='unity-scope-manpages', 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-manpages.service']), ('share/unity-scopes/manpages', ['src/unity_manpages_daemon.py']), ('share/unity-scopes/manpages', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n, }) unity-scope-manpages-3.0+14.04.20140324/setup.cfg0000644000015201777760000000020512314061141021627 0ustar pbusernogroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-manpages desktop_files=[('share/unity/scopes/code', ('data/manpages.scope.in',))] unity-scope-manpages-3.0+14.04.20140324/po/0000755000015201777760000000000012314061370020433 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/po/POTFILES.in0000644000015201777760000000013112314061141022177 0ustar pbusernogroup00000000000000[encoding: UTF-8] src/unity_manpages_daemon.py [type: gettext/ini]data/manpages.scope.in unity-scope-manpages-3.0+14.04.20140324/po/unity-scope-manpages.pot0000644000015201777760000000263112314061141025225 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_manpages_daemon.py:37 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-05-13 18:42+0200\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_manpages_daemon.py:35 msgid "Search Manpages" msgstr "" #: ../src/unity_manpages_daemon.py:36 msgid "Sorry, there are no Manpages that match your search." msgstr "" #: ../src/unity_manpages_daemon.py:45 msgid "Technical Documents" msgstr "" #: ../src/unity_manpages_daemon.py:99 msgid "Show" msgstr "" #: ../data/manpages.scope.in.h:1 msgid "manpages;" msgstr "" #: ../data/manpages.scope.in.h:2 msgid "Manpages" msgstr "" #: ../data/manpages.scope.in.h:3 msgid "" "This is an Ubuntu search plugin that enables information from local manpages " "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." msgstr "" #: ../data/manpages.scope.in.h:4 msgid "Search for Manpages" msgstr "" unity-scope-manpages-3.0+14.04.20140324/MANIFEST.in0000644000015201777760000000007612314061141021552 0ustar pbusernogroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-manpages-3.0+14.04.20140324/src/0000755000015201777760000000000012314061370020604 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/src/__init__.py0000644000015201777760000000000012314061141022677 0ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/src/unity_manpages_daemon.py0000755000015201777760000001543312314061153025534 0ustar pbusernogroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- # Copyright(C) 2012 Pawel Stolowski # 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, Gtk from gi.repository import Unity import gettext import subprocess import re import os APP_NAME = 'unity-scope-manpages' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Development.Manpages' UNIQUE_PATH = '/com/canonical/unity/scope/development/manpages' SEARCH_HINT = _('Search Manpages') NO_RESULTS_HINT = _('Sorry, there are no Manpages that match your search.') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR + 'service-manpages.svg' DEFAULT_RESULT_ICON = SVG_DIR + 'service-manpages.svg' DEFAULT_RESULT_MIMETYPE = 'x-scheme-handler/man' DEFAULT_RESULT_TYPE = Unity.ResultType.DEFAULT c1 = {'id': 'documentation', 'name': _('Technical Documents'), 'icon': SVG_DIR + 'group-installed.svg', 'renderer': Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1] FILTERS = [] EXTRA_METADATA = [] regex_apropos = re.compile('^(.+?)\s+\((\d+)\)\s+-\s(.+?)$') def search(search, filters): ''' Use apropos to search for manpages matching the search string ''' results = [] icon_hint = Gio.ThemedIcon.new("text-x-generic").to_string() result = [] if len(search) > 2: # don't run apropos for strings shorter than 3 chars apropos = subprocess.Popen(["apropos", search], stdout=subprocess.PIPE) os.waitpid(apropos.pid, 0) out = apropos.communicate()[0] out = out.decode('utf8') for line in out.split("\n"): m = regex_apropos.match(line) if m: result.append((m.group(1), m.group(2), m.group(3))) for res in result: uri = 'man:' + res[0] + '(' + res[1] + ')' icon_theme = Gtk.IconTheme() icon_info = icon_theme.lookup_icon(res[0], 128, 0) if icon_info: icon_hint = Gio.ThemedIcon.new(res[0]).to_string() else: icon_hint = None results.append({'uri': uri, 'icon': icon_hint, 'category': 0, 'title': res[0], 'comment': res[2]}) return results class Preview(Unity.ResultPreviewer): def do_run(self): preview = Unity.GenericPreview.new(self.result.title, '', None) preview.props.subtitle = self.result.comment image = Gio.ThemedIcon.new(self.result.icon_hint) preview.props.image = image manpage = subprocess.check_output(['man', self.result.title]) match = re.search('NAME', manpage.decode('utf-8')) description = manpage.decode('utf-8')[match.start():] description = description.replace('‐\n ', '') if len(description) > 5000: description = description[:5000] + '…' preview.props.description_markup = description icon = Gio.FileIcon.new (Gio.file_new_for_path(PROVIDER_ICON)) view_action = Unity.PreviewAction.new("open", _("Open"), icon) 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']) 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_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-manpages-3.0+14.04.20140324/data/0000755000015201777760000000000012314061370020726 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/data/unity-scope-manpages.service0000644000015201777760000000023612314061141026355 0ustar pbusernogroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Development.Manpages Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s code/manpages.scope unity-scope-manpages-3.0+14.04.20140324/data/icons/0000755000015201777760000000000012314061370022041 5ustar pbusernogroup00000000000000unity-scope-manpages-3.0+14.04.20140324/data/icons/service-manpages.svg0000644000015201777760000002700312314061141026011 0ustar pbusernogroup00000000000000 image/svg+xml unity-scope-manpages-3.0+14.04.20140324/data/manpages.scope.in0000644000015201777760000000136612314061153024166 0ustar pbusernogroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Development.Manpages DBusPath=/com/canonical/unity/scope/development/manpages Icon=/usr/share/icons/unity-icon-theme/places/svg/service-manpages.svg _Keywords=manpages;man; RequiredMetadata= OptionalMetadata= Loader=/usr/share/unity-scopes/manpages/unity_manpages_daemon.py Module=manpages.unity_manpages_daemon ModuleType=python3 RemoteContent=false Type=code _Name=Manpages _Description=This is an Ubuntu search plugin that enables information from local manpages 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 for Manpages [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-manpages