(trunk-1599/1600/1601)

* setup.py can install the manual (and by extension do can debuild)
* setup.py has (inactive) code for generating the html from the source
  but this will break if rtd theme is not available
* A few changes to doc strings to make the autodoc prettier
* Added help shortcut, by default F1 to open the local manual
* Added button to About tab to launch manual
* A couple of additional string to translate related to manual/help

* Small tweak to setup.py to seperate build and install, and always attempt
  to install manual by default.

* Small fix for systems (i.e. my 12.04 LTS) that don't set LANGUAGE for
  whatever reason. This breaks the manual lookup
This commit is contained in:
Stephen Boddy 2015-09-01 22:50:09 +02:00
parent 825214da1e
commit f64d3e67fa
87 changed files with 18467 additions and 17762 deletions

464
po/af.po

File diff suppressed because it is too large Load Diff

467
po/ar.po

File diff suppressed because it is too large Load Diff

464
po/ast.po

File diff suppressed because it is too large Load Diff

464
po/az.po

File diff suppressed because it is too large Load Diff

465
po/be.po

File diff suppressed because it is too large Load Diff

468
po/bg.po

File diff suppressed because it is too large Load Diff

468
po/bn.po

File diff suppressed because it is too large Load Diff

464
po/bs.po

File diff suppressed because it is too large Load Diff

464
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

464
po/ckb.po

File diff suppressed because it is too large Load Diff

468
po/cs.po

File diff suppressed because it is too large Load Diff

464
po/da.po

File diff suppressed because it is too large Load Diff

468
po/de.po

File diff suppressed because it is too large Load Diff

464
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

464
po/eo.po

File diff suppressed because it is too large Load Diff

467
po/es.po

File diff suppressed because it is too large Load Diff

464
po/et.po

File diff suppressed because it is too large Load Diff

471
po/eu.po

File diff suppressed because it is too large Load Diff

464
po/fa.po

File diff suppressed because it is too large Load Diff

464
po/fi.po

File diff suppressed because it is too large Load Diff

464
po/fo.po

File diff suppressed because it is too large Load Diff

468
po/fr.po

File diff suppressed because it is too large Load Diff

464
po/fy.po

File diff suppressed because it is too large Load Diff

464
po/ga.po

File diff suppressed because it is too large Load Diff

467
po/gl.po

File diff suppressed because it is too large Load Diff

464
po/he.po

File diff suppressed because it is too large Load Diff

467
po/hi.po

File diff suppressed because it is too large Load Diff

467
po/hr.po

File diff suppressed because it is too large Load Diff

464
po/hu.po

File diff suppressed because it is too large Load Diff

464
po/hy.po

File diff suppressed because it is too large Load Diff

464
po/id.po

File diff suppressed because it is too large Load Diff

464
po/is.po

File diff suppressed because it is too large Load Diff

471
po/it.po

File diff suppressed because it is too large Load Diff

479
po/ja.po

File diff suppressed because it is too large Load Diff

464
po/jv.po

File diff suppressed because it is too large Load Diff

464
po/ka.po

File diff suppressed because it is too large Load Diff

464
po/kk.po

File diff suppressed because it is too large Load Diff

481
po/ko.po

File diff suppressed because it is too large Load Diff

464
po/la.po

File diff suppressed because it is too large Load Diff

464
po/lt.po

File diff suppressed because it is too large Load Diff

464
po/lv.po

File diff suppressed because it is too large Load Diff

464
po/mk.po

File diff suppressed because it is too large Load Diff

464
po/ml.po

File diff suppressed because it is too large Load Diff

464
po/mr.po

File diff suppressed because it is too large Load Diff

471
po/ms.po

File diff suppressed because it is too large Load Diff

472
po/nb.po

File diff suppressed because it is too large Load Diff

464
po/nl.po

File diff suppressed because it is too large Load Diff

464
po/nn.po

File diff suppressed because it is too large Load Diff

464
po/oc.po

File diff suppressed because it is too large Load Diff

464
po/pl.po

File diff suppressed because it is too large Load Diff

468
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

467
po/ro.po

File diff suppressed because it is too large Load Diff

474
po/ru.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

464
po/si.po

File diff suppressed because it is too large Load Diff

468
po/sk.po

File diff suppressed because it is too large Load Diff

464
po/sl.po

File diff suppressed because it is too large Load Diff

464
po/sq.po

File diff suppressed because it is too large Load Diff

464
po/sr.po

File diff suppressed because it is too large Load Diff

464
po/su.po

File diff suppressed because it is too large Load Diff

468
po/sv.po

File diff suppressed because it is too large Load Diff

485
po/ta.po

File diff suppressed because it is too large Load Diff

464
po/te.po

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-08-04 20:49+0200\n" "POT-Creation-Date: 2015-09-01 22:49+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -208,11 +208,11 @@ msgstr ""
msgid "Launch" msgid "Launch"
msgstr "" msgstr ""
#: ../terminatorlib/notebook.py:348 #: ../terminatorlib/notebook.py:350
msgid "tab" msgid "tab"
msgstr "" msgstr ""
#: ../terminatorlib/notebook.py:564 #: ../terminatorlib/notebook.py:566
msgid "Close Tab" msgid "Close Tab"
msgstr "" msgstr ""
@ -1015,14 +1015,6 @@ msgstr ""
#: ../terminatorlib/preferences.glade.h:145 #: ../terminatorlib/preferences.glade.h:145
msgid "" msgid ""
"<a href=\"http://gnometerminator.blogspot.com/p/introduction.html"
"\">Homepage</a>\n"
"<a href=\"http://gnometerminator.blogspot.com/\">Blog / News</a>\n"
"<a href=\"https://launchpad.net/terminator\">Development</a>"
msgstr ""
#: ../terminatorlib/preferences.glade.h:148
msgid ""
"The goal of this project is to produce a useful tool for arranging " "The goal of this project is to produce a useful tool for arranging "
"terminals. It is inspired by programs such as gnome-multi-term, quadkonsole, " "terminals. It is inspired by programs such as gnome-multi-term, quadkonsole, "
"etc. in that the main focus is arranging terminals in grids (tabs is the " "etc. in that the main focus is arranging terminals in grids (tabs is the "
@ -1035,7 +1027,19 @@ msgid ""
"the Development link)" "the Development link)"
msgstr "" msgstr ""
#: ../terminatorlib/preferences.glade.h:151 #: ../terminatorlib/preferences.glade.h:148
msgid "The Manual"
msgstr ""
#: ../terminatorlib/preferences.glade.h:149
msgid ""
"<a href=\"http://gnometerminator.blogspot.com/p/introduction.html"
"\">Homepage</a>\n"
"<a href=\"http://gnometerminator.blogspot.com/\">Blog / News</a>\n"
"<a href=\"https://launchpad.net/terminator\">Development</a>"
msgstr ""
#: ../terminatorlib/preferences.glade.h:152
msgid "About" msgid "About"
msgstr "" msgstr ""
@ -1307,11 +1311,15 @@ msgstr ""
msgid "Switch to previous profile" msgid "Switch to previous profile"
msgstr "" msgstr ""
#: ../terminatorlib/prefseditor.py:1032 ../terminatorlib/prefseditor.py:1037 #: ../terminatorlib/prefseditor.py:153
msgid "Open the manual"
msgstr ""
#: ../terminatorlib/prefseditor.py:1033 ../terminatorlib/prefseditor.py:1038
msgid "New Profile" msgid "New Profile"
msgstr "" msgstr ""
#: ../terminatorlib/prefseditor.py:1077 ../terminatorlib/prefseditor.py:1082 #: ../terminatorlib/prefseditor.py:1078 ../terminatorlib/prefseditor.py:1083
msgid "New Layout" msgid "New Layout"
msgstr "" msgstr ""
@ -1439,77 +1447,77 @@ msgstr ""
msgid "Other Encodings" msgid "Other Encodings"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:455 #: ../terminatorlib/terminal.py:454
msgid "N_ew group..." msgid "N_ew group..."
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:461 #: ../terminatorlib/terminal.py:460
msgid "_None" msgid "_None"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:481 #: ../terminatorlib/terminal.py:480
#, python-format #, python-format
msgid "Remove group %s" msgid "Remove group %s"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:486 #: ../terminatorlib/terminal.py:485
msgid "G_roup all in tab" msgid "G_roup all in tab"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:491 #: ../terminatorlib/terminal.py:490
msgid "Ungro_up all in tab" msgid "Ungro_up all in tab"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:496 #: ../terminatorlib/terminal.py:495
msgid "Remove all groups" msgid "Remove all groups"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:503 #: ../terminatorlib/terminal.py:502
#, python-format #, python-format
msgid "Close group %s" msgid "Close group %s"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:513 #: ../terminatorlib/terminal.py:512
msgid "Broadcast _all" msgid "Broadcast _all"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:514 #: ../terminatorlib/terminal.py:513
msgid "Broadcast _group" msgid "Broadcast _group"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:515 #: ../terminatorlib/terminal.py:514
msgid "Broadcast _off" msgid "Broadcast _off"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:531 #: ../terminatorlib/terminal.py:530
msgid "_Split to this group" msgid "_Split to this group"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:536 #: ../terminatorlib/terminal.py:535
msgid "Auto_clean groups" msgid "Auto_clean groups"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:543 #: ../terminatorlib/terminal.py:542
msgid "_Insert terminal number" msgid "_Insert terminal number"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:547 #: ../terminatorlib/terminal.py:546
msgid "Insert _padded terminal number" msgid "Insert _padded terminal number"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:1359 #: ../terminatorlib/terminal.py:1355
msgid "Unable to find a shell" msgid "Unable to find a shell"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:1390 #: ../terminatorlib/terminal.py:1386
msgid "Unable to start shell:" msgid "Unable to start shell:"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:1783 #: ../terminatorlib/terminal.py:1779
msgid "Rename Window" msgid "Rename Window"
msgstr "" msgstr ""
#: ../terminatorlib/terminal.py:1792 #: ../terminatorlib/terminal.py:1788
msgid "Enter a new title for the Terminator window..." msgid "Enter a new title for the Terminator window..."
msgstr "" msgstr ""

464
po/th.po

File diff suppressed because it is too large Load Diff

464
po/tr.po

File diff suppressed because it is too large Load Diff

464
po/tyv.po

File diff suppressed because it is too large Load Diff

471
po/uk.po

File diff suppressed because it is too large Load Diff

464
po/ur.po

File diff suppressed because it is too large Load Diff

464
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,13 +18,18 @@ from terminatorlib.version import APP_NAME, APP_VERSION
PO_DIR = 'po' PO_DIR = 'po'
MO_DIR = os.path.join('build', 'mo') MO_DIR = os.path.join('build', 'mo')
DOC_DIR = 'doc'
class TerminatorDist(Distribution): class TerminatorDist(Distribution):
global_options = Distribution.global_options + [ global_options = Distribution.global_options + [
("build-documentation", None, "Build the documentation"),
("install-documentation", None, "Install the documentation"),
("without-gettext", None, "Don't build/install gettext .mo files"), ("without-gettext", None, "Don't build/install gettext .mo files"),
("without-icon-cache", None, "Don't attempt to run gtk-update-icon-cache")] ("without-icon-cache", None, "Don't attempt to run gtk-update-icon-cache")]
def __init__ (self, *args): def __init__ (self, *args):
self.build_documentation = False
self.install_documentation = True
self.without_gettext = False self.without_gettext = False
self.without_icon_cache = False self.without_icon_cache = False
Distribution.__init__(self, *args) Distribution.__init__(self, *args)
@ -34,36 +39,50 @@ class BuildData(build):
def run (self): def run (self):
build.run (self) build.run (self)
if self.distribution.without_gettext: if not self.distribution.without_gettext:
return # Build the translations
for po in glob.glob (os.path.join (PO_DIR, '*.po')):
lang = os.path.basename(po[:-3])
mo = os.path.join(MO_DIR, lang, 'terminator.mo')
for po in glob.glob (os.path.join (PO_DIR, '*.po')): directory = os.path.dirname(mo)
lang = os.path.basename(po[:-3]) if not os.path.exists(directory):
mo = os.path.join(MO_DIR, lang, 'terminator.mo') info('creating %s' % directory)
os.makedirs(directory)
directory = os.path.dirname(mo) if newer(po, mo):
if not os.path.exists(directory): info('compiling %s -> %s' % (po, mo))
info('creating %s' % directory) try:
os.makedirs(directory) rc = subprocess.call(['msgfmt', '-o', mo, po])
if rc != 0:
raise Warning, "msgfmt returned %d" % rc
except Exception, e:
error("Building gettext files failed. Try setup.py --without-gettext [build|install]")
error("Error: %s" % str(e))
sys.exit(1)
if newer(po, mo): TOP_BUILDDIR='.'
info('compiling %s -> %s' % (po, mo)) INTLTOOL_MERGE='intltool-merge'
try: desktop_in='data/terminator.desktop.in'
rc = subprocess.call(['msgfmt', '-o', mo, po]) desktop_data='data/terminator.desktop'
if rc != 0: os.system ("C_ALL=C " + INTLTOOL_MERGE + " -d -u -c " + TOP_BUILDDIR +
raise Warning, "msgfmt returned %d" % rc "/po/.intltool-merge-cache " + TOP_BUILDDIR + "/po " +
except Exception, e: desktop_in + " " + desktop_data)
error("Building gettext files failed. Try setup.py --without-gettext [build|install]") appdata_in='data/terminator.appdata.xml.in'
error("Error: %s" % str(e)) appdata_data='data/terminator.appdata.xml'
sys.exit(1) os.system ("C_ALL=C " + INTLTOOL_MERGE + " -x -u -c " + TOP_BUILDDIR +
"/po/.intltool-merge-cache " + TOP_BUILDDIR + "/po " +
appdata_in + " " + appdata_data)
TOP_BUILDDIR='.' if self.distribution.build_documentation:
INTLTOOL_MERGE='intltool-merge' # Build the documentation
desktop_in='data/terminator.desktop.in' for doc_folder in (glob.glob (os.path.join (DOC_DIR, 'manual*')) + [os.path.join (DOC_DIR, 'apidoc')]):
desktop_data='data/terminator.desktop' if os.path.isfile(os.path.join(doc_folder, 'Makefile')):
os.system ("C_ALL=C " + INTLTOOL_MERGE + " -d -u -c " + TOP_BUILDDIR + old_cwd = os.getcwd()
"/po/.intltool-merge-cache " + TOP_BUILDDIR + "/po " + os.chdir(doc_folder)
desktop_in + " " + desktop_data) os.system("make clean")
os.system("make html")
os.chdir(old_cwd)
class Uninstall(Command): class Uninstall(Command):
description = "Attempt an uninstall from an install --record file" description = "Attempt an uninstall from an install --record file"
@ -126,6 +145,7 @@ class Uninstall(Command):
class InstallData(install_data): class InstallData(install_data):
def run (self): def run (self):
self.data_files.extend (self._find_mo_files ()) self.data_files.extend (self._find_mo_files ())
self.data_files.extend (self._find_doc_files ())
install_data.run (self) install_data.run (self)
if not self.distribution.without_icon_cache: if not self.distribution.without_icon_cache:
self._update_icon_cache () self._update_icon_cache ()
@ -149,6 +169,27 @@ class InstallData(install_data):
return data_files return data_files
def _find_doc_files (self):
data_files = []
if self.distribution.install_documentation:
for doc_folder in (glob.glob (os.path.join (DOC_DIR, 'manual*')) + [os.path.join (DOC_DIR, 'apidoc')]):
# construct new path
src = os.path.join(doc_folder, '_build', 'html')
dest_sub = os.path.split(doc_folder[:])[1]
if dest_sub[:6] == 'manual':
dest_sub = 'html'+dest_sub[6:]
dest = os.path.join('share', 'doc', 'terminator', dest_sub)
if os.path.isdir(src):
for dirpath, dirnames, filenames in os.walk(src):
cut_elem_count = len(doc_folder.split(os.sep)) + 2
dest_sub = os.path.join(dirpath.split(os.sep)[cut_elem_count:])
full_dest_folder = os.path.join(dest, *dest_sub)
full_src_filenames = [os.path.join(dirpath, filename) for filename in filenames]
data_files.append((full_dest_folder, full_src_filenames))
return data_files
class Test(Command): class Test(Command):
user_options = [] user_options = []
def initialize_options(self): def initialize_options(self):

View File

@ -2,10 +2,11 @@
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""borg.py - We are the borg. Resistance is futile. """borg.py - We are the borg. Resistance is futile.
http://code.activestate.com/recipes/66531/
ActiveState's policy appears to be that snippets http://code.activestate.com/recipes/66531/
exist to encourage re-use, but I can not find any ActiveState's policy appears to be that snippets
specific licencing terms. exist to encourage re-use, but I can not find any
specific licencing terms.
""" """
from util import dbg from util import dbg
@ -16,20 +17,18 @@ class Borg:
"""Definition of a class that can never be duplicated. Correct usage is """Definition of a class that can never be duplicated. Correct usage is
thus: thus:
from borg import Borg >>> from borg import Borg
class foo(Borg): >>> class foo(Borg):
# All attributes on a borg class *must* = None ... # All attributes on a borg class *must* = None
attribute = None ... attribute = None
... def __init__(self):
def __init__(self): ... Borg.__init__(self, self.__class__.__name__)
Borg.__init__(self, self.__class__.__name__) ... def prepare_attributes(self):
... if not self.attribute:
def prepare_attributes(self): ... self.attribute = []
if not self.attribute: ...
self.attribute = [] >>> bar = foo()
>>> bar.prepare_attributes()
bar = foo()
bar.prepare_attributes()
The important thing to note is that all attributes of borg classes *must* be The important thing to note is that all attributes of borg classes *must* be
declared as being None. If you attempt to use static class attributes you declared as being None. If you attempt to use static class attributes you

View File

@ -191,7 +191,8 @@ DEFAULTS = {
'edit_window_title': '<Alt>t', 'edit_window_title': '<Alt>t',
'layout_launcher' : '<Alt>l', 'layout_launcher' : '<Alt>l',
'next_profile' : '', 'next_profile' : '',
'previous_profile' : '' 'previous_profile' : '',
'help' : 'F1'
}, },
'profiles': { 'profiles': {
'default': { 'default': {

View File

@ -1191,12 +1191,6 @@ class ConfigObj(Section):
write_empty_values=False, _inspec=False): write_empty_values=False, _inspec=False):
""" """
Parse a config file or create a config file object. Parse a config file or create a config file object.
``ConfigObj(infile=None, configspec=None, encoding=None,
interpolation=True, raise_errors=False, list_values=True,
create_empty=False, file_error=False, stringify=True,
indent_type=None, default_encoding=None, unrepr=False,
write_empty_values=False, _inspec=False)``
""" """
self._inspec = _inspec self._inspec = _inspec
# init the superclass # init the superclass

View File

@ -160,7 +160,6 @@ __all__ = (
'is_ip_addr_list', 'is_ip_addr_list',
'is_mixed_list', 'is_mixed_list',
'is_option', 'is_option',
'__docformat__',
) )
@ -481,7 +480,7 @@ class Validator(object):
... if not value <= max: ... if not value <= max:
... raise VdtValueTooBigError(value) ... raise VdtValueTooBigError(value)
... return value ... return value
...
>>> fdict = {'int_range': int_range_check} >>> fdict = {'int_range': int_range_check}
>>> vtr1 = Validator(fdict) >>> vtr1 = Validator(fdict)
>>> vtr1.check('int_range(20, 40)', '30') >>> vtr1.check('int_range(20, 40)', '30')
@ -571,6 +570,7 @@ class Validator(object):
Arguments: Arguments:
check: string representing check to apply (including arguments) check: string representing check to apply (including arguments)
value: object to be checked value: object to be checked
Returns value, converted to correct type if necessary Returns value, converted to correct type if necessary
If the check fails, raises a ``ValidateError`` subclass. If the check fails, raises a ``ValidateError`` subclass.

View File

@ -3864,25 +3864,6 @@
<property name="y_options">GTK_FILL</property> <property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkLabel" id="label29">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="xalign">1</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">&lt;a href="http://gnometerminator.blogspot.com/p/introduction.html"&gt;Homepage&lt;/a&gt;
&lt;a href="http://gnometerminator.blogspot.com/"&gt;Blog / News&lt;/a&gt;
&lt;a href="https://launchpad.net/terminator"&gt;Development&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="justify">right</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="label27"> <object class="GtkLabel" id="label27">
<property name="visible">True</property> <property name="visible">True</property>
@ -3904,6 +3885,50 @@ Much of the behavior of Terminator is based on GNOME Terminal, and we are adding
<property name="y_options">GTK_FILL</property> <property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkVBox" id="vbox19">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">The Manual</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_open_manual" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label29">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">&lt;a href="http://gnometerminator.blogspot.com/p/introduction.html"&gt;Homepage&lt;/a&gt;
&lt;a href="http://gnometerminator.blogspot.com/"&gt;Blog / News&lt;/a&gt;
&lt;a href="https://launchpad.net/terminator"&gt;Development&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"/>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>

View File

@ -149,7 +149,8 @@ class PrefsEditor:
'edit_window_title': _('Edit window title'), 'edit_window_title': _('Edit window title'),
'layout_launcher' : _('Open layout launcher window'), 'layout_launcher' : _('Open layout launcher window'),
'next_profile' : _('Switch to next profile'), 'next_profile' : _('Switch to next profile'),
'previous_profile' : _('Switch to previous profile') 'previous_profile' : _('Switch to previous profile'),
'help' : _('Open the manual')
} }
def __init__ (self, term): def __init__ (self, term):
@ -1411,6 +1412,10 @@ class PrefsEditor:
self.config['keybindings'][binding] = None self.config['keybindings'][binding] = None
self.config.save() self.config.save()
def on_open_manual(self, widget):
"""Open the fine manual"""
self.term.key_help()
class LayoutEditor: class LayoutEditor:
profile_ids_to_profile = None profile_ids_to_profile = None
profile_profile_to_ids = None profile_profile_to_ids = None

View File

@ -13,7 +13,7 @@ from gi.repository import Vte
import subprocess import subprocess
import urllib import urllib
from util import dbg, err, spawn_new_terminator, make_uuid from util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup
import util import util
from config import Config from config import Config
from cwd import get_default_cwd from cwd import get_default_cwd
@ -1826,6 +1826,11 @@ class Terminal(Gtk.VBox):
def key_line_down(self): def key_line_down(self):
self.scroll_by_line(1) self.scroll_by_line(1)
def key_help(self):
manual_index_page = manual_lookup()
if manual_index_page:
self.open_url('file://%s' % (manual_index_page))
# End key events # End key events
GObject.type_register(Terminal) GObject.type_register(Terminal)

View File

@ -14,14 +14,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
"""Terminator.util - misc utility functions """Terminator.util - misc utility functions"""
>>> a = {'foo': 'bar', 'baz': 'bjonk'}
>>> b = {'foo': 'far', 'baz': 'bjonk'}
>>> dict_diff(a, b)
{'foo': 'far'}
"""
import sys import sys
from gi.repository import Gtk, Gdk from gi.repository import Gtk, Gdk
@ -92,6 +85,26 @@ def has_ancestor(widget, wtype):
return(True) return(True)
return(False) return(False)
def manual_lookup():
'''Choose the manual to open based on LANGUAGE'''
prefix = os.path.join(os.sep, 'usr', 'share', 'doc', 'terminator')
if 'LANGUAGE' in os.environ:
languages = os.environ['LANGUAGE'].split(':')
for language in languages:
full_path = os.path.join(prefix, 'html_%s' % (language), 'index.html')
if os.path.isfile(full_path):
dbg('Found %s manual' % (language))
return full_path
dbg('Couldn\'t find manual for %s language' % (language))
full_path = os.path.join(prefix, 'html', 'index.html')
if os.path.isfile(full_path):
dbg('Falling back to the default manual')
return full_path
else:
dbg('I can\'t find any suitable manual')
return None
def path_lookup(command): def path_lookup(command):
'''Find a command in our path''' '''Find a command in our path'''
if os.path.isabs(command): if os.path.isabs(command):
@ -183,7 +196,13 @@ def get_config_dir():
def dict_diff(reference, working): def dict_diff(reference, working):
"""Examine the values in the supplied working set and return a new dict """Examine the values in the supplied working set and return a new dict
that only contains those values which are different from those in the that only contains those values which are different from those in the
reference dictionary""" reference dictionary
>>> a = {'foo': 'bar', 'baz': 'bjonk'}
>>> b = {'foo': 'far', 'baz': 'bjonk'}
>>> dict_diff(a, b)
{'foo': 'far'}
"""
result = {} result = {}