Merge pull request #6 from gnome-terminator/python3

Implement support for Python 3
This commit is contained in:
Markus Frosch 2020-04-05 19:54:57 +02:00 committed by GitHub
commit c0007818bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 353 additions and 4309 deletions

View File

@ -7,9 +7,6 @@ terminator.py
data/terminator.desktop.in data/terminator.desktop.in
data/terminator.appdata.xml.in data/terminator.appdata.xml.in
terminatorlib/borg.py terminatorlib/borg.py
terminatorlib/configobj/configobj.py
terminatorlib/configobj/__init__.py
terminatorlib/configobj/validate.py
terminatorlib/config.py terminatorlib/config.py
terminatorlib/container.py terminatorlib/container.py
terminatorlib/cwd.py terminatorlib/cwd.py

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python2 #!/usr/bin/env python
#
# remotinator - send commands to Terminator via DBus # remotinator - send commands to Terminator via DBus
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
from distutils.core import setup from distutils.core import setup
from distutils.dist import Distribution from distutils.dist import Distribution
@ -53,8 +53,8 @@ class BuildData(build):
try: try:
rc = subprocess.call(['msgfmt', '-o', mo, po]) rc = subprocess.call(['msgfmt', '-o', mo, po])
if rc != 0: if rc != 0:
raise Warning, "msgfmt returned %d" % rc raise Warning("msgfmt returned %d" % rc)
except Exception, e: except Exception as e:
error("Building gettext files failed. Ensure you have gettext installed. Alternatively, try setup.py --without-gettext [build|install]") error("Building gettext files failed. Ensure you have gettext installed. Alternatively, try setup.py --without-gettext [build|install]")
error("Error: %s" % str(e)) error("Error: %s" % str(e))
sys.exit(1) sys.exit(1)
@ -104,7 +104,7 @@ class Uninstall(Command):
raise DistutilsFileError("Pass manifest with --manifest=file") raise DistutilsFileError("Pass manifest with --manifest=file")
f = open(self.manifest) f = open(self.manifest)
files = [file.strip() for file in f] files = [file.strip() for file in f]
except IOError, e: except IOError as e:
raise DistutilsFileError("unable to open install manifest: %s", str(e)) raise DistutilsFileError("unable to open install manifest: %s", str(e))
finally: finally:
if f: if f:
@ -116,7 +116,7 @@ class Uninstall(Command):
if not self.dry_run: if not self.dry_run:
try: try:
os.unlink(file) os.unlink(file)
except OSError, e: except OSError as e:
warn("could not delete: %s" % repr(file)) warn("could not delete: %s" % repr(file))
elif not os.path.isdir(file): elif not os.path.isdir(file):
info("skipping %s" % repr(file)) info("skipping %s" % repr(file))
@ -133,7 +133,7 @@ class Uninstall(Command):
if not self.dry_run: if not self.dry_run:
try: try:
os.rmdir(dir) os.rmdir(dir)
except OSError, e: except OSError as e:
warn("could not remove directory: %s" % str(e)) warn("could not remove directory: %s" % str(e))
else: else:
info("skipping empty directory %s" % repr(dir)) info("skipping empty directory %s" % repr(dir))
@ -152,7 +152,7 @@ class InstallData(install_data):
info("running gtk-update-icon-cache") info("running gtk-update-icon-cache")
try: try:
subprocess.call(["gtk-update-icon-cache", "-q", "-f", "-t", os.path.join(self.install_dir, "share/icons/hicolor")]) subprocess.call(["gtk-update-icon-cache", "-q", "-f", "-t", os.path.join(self.install_dir, "share/icons/hicolor")])
except Exception, e: except Exception as e:
warn("updating the GTK icon cache failed: %s" % str(e)) warn("updating the GTK icon cache failed: %s" % str(e))
def _find_mo_files (self): def _find_mo_files (self):
@ -231,7 +231,6 @@ setup(name=APP_NAME,
], ],
packages=[ packages=[
'terminatorlib', 'terminatorlib',
'terminatorlib.configobj',
'terminatorlib.plugins', 'terminatorlib.plugins',
], ],
install_requires=[ install_requires=[

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python2 #!/usr/bin/env python
#
# Terminator - multiple gnome terminals in one window # Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -92,7 +93,7 @@ if __name__ == '__main__':
if OPTIONS.working_directory is None: if OPTIONS.working_directory is None:
OPTIONS.working_directory = ORIGCWD OPTIONS.working_directory = ORIGCWD
optionslist = {} optionslist = {}
for opt, val in OPTIONS.__dict__.items(): for opt, val in list(OPTIONS.__dict__.items()):
if type(val) == type([]): if type(val) == type([]):
val = ' '.join(val) val = ' '.join(val)
if val == True: if val == True:
@ -120,12 +121,12 @@ if __name__ == '__main__':
try: try:
dbg('Creating a terminal with layout: %s' % OPTIONS.layout) dbg('Creating a terminal with layout: %s' % OPTIONS.layout)
TERMINATOR.create_layout(OPTIONS.layout) TERMINATOR.create_layout(OPTIONS.layout)
except (KeyError,ValueError), ex: except (KeyError,ValueError) as ex:
err('layout creation failed, creating a window ("%s")' % ex) err('layout creation failed, creating a window ("%s")' % ex)
TERMINATOR.new_window() TERMINATOR.new_window()
TERMINATOR.layout_done() TERMINATOR.layout_done()
if OPTIONS.debug >= 2: if OPTIONS.debug and OPTIONS.debug >= 2:
import terminatorlib.debugserver as debugserver import terminatorlib.debugserver as debugserver
# pylint: disable-msg=W0611 # pylint: disable-msg=W0611
import threading import threading

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window # Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #

5
terminatorlib/borg.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# 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.
@ -9,7 +8,7 @@ exist to encourage re-use, but I can not find any
specific licencing terms. specific licencing terms.
""" """
from util import dbg from .util import dbg
# pylint: disable-msg=R0903 # pylint: disable-msg=R0903
# pylint: disable-msg=R0921 # pylint: disable-msg=R0921
@ -43,7 +42,7 @@ class Borg:
type.""" type."""
if borgtype is None: if borgtype is None:
raise TypeError('Borg::__init__: You must pass a borgtype') raise TypeError('Borg::__init__: You must pass a borgtype')
if not self.__shared_state.has_key(borgtype): if borgtype not in self.__shared_state:
dbg('Borg::__init__: Preparing borg state for %s' % borgtype) dbg('Borg::__init__: Preparing borg state for %s' % borgtype)
self.__shared_state[borgtype] = {} self.__shared_state[borgtype] = {}
self.__dict__ = self.__shared_state[borgtype] self.__dict__ = self.__shared_state[borgtype]

69
terminatorlib/config.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# TerminatorConfig - layered config classes # TerminatorConfig - layered config classes
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -71,13 +70,12 @@ KeyError: 'ConfigBase::get_item: unknown key algo'
""" """
import platform
import os import os
from copy import copy from copy import copy
from configobj.configobj import ConfigObj, flatten_errors from configobj import ConfigObj, flatten_errors
from configobj.validate import Validator from validate import Validator
from borg import Borg from .borg import Borg
from util import dbg, err, DEBUG, get_config_dir, dict_diff from .util import dbg, err, DEBUG, get_config_dir, dict_diff
from gi.repository import Gio from gi.repository import Gio
@ -298,7 +296,7 @@ class Config(object):
profile = options.profile profile = options.profile
dbg('Config::set_profile: Changing profile to %s' % profile) dbg('Config::set_profile: Changing profile to %s' % profile)
self.profile = profile self.profile = profile
if not self.base.profiles.has_key(profile): if profile not in self.base.profiles:
dbg('Config::set_profile: %s does not exist, creating' % profile) dbg('Config::set_profile: %s does not exist, creating' % profile)
self.base.profiles[profile] = copy(DEFAULTS['profiles']['default']) self.base.profiles[profile] = copy(DEFAULTS['profiles']['default'])
@ -313,7 +311,7 @@ class Config(object):
# remove a profile # remove a profile
err('Config::del_profile: Deleting in-use profile %s.' % profile) err('Config::del_profile: Deleting in-use profile %s.' % profile)
self.set_profile('default') self.set_profile('default')
if self.base.profiles.has_key(profile): if profile in self.base.profiles:
del(self.base.profiles[profile]) del(self.base.profiles[profile])
options = self.options_get() options = self.options_get()
if options and options.profile == profile: if options and options.profile == profile:
@ -322,7 +320,7 @@ class Config(object):
def rename_profile(self, profile, newname): def rename_profile(self, profile, newname):
"""Rename a profile""" """Rename a profile"""
if self.base.profiles.has_key(profile): if profile in self.base.profiles:
self.base.profiles[newname] = self.base.profiles[profile] self.base.profiles[newname] = self.base.profiles[profile]
del(self.base.profiles[profile]) del(self.base.profiles[profile])
if profile == self.profile: if profile == self.profile:
@ -330,7 +328,7 @@ class Config(object):
def list_profiles(self): def list_profiles(self):
"""List all configured profiles""" """List all configured profiles"""
return(self.base.profiles.keys()) return(list(self.base.profiles.keys()))
def add_layout(self, name, layout): def add_layout(self, name, layout):
"""Add a new layout""" """Add a new layout"""
@ -342,18 +340,18 @@ class Config(object):
def del_layout(self, layout): def del_layout(self, layout):
"""Delete a layout""" """Delete a layout"""
if self.base.layouts.has_key(layout): if layout in self.base.layouts:
del(self.base.layouts[layout]) del(self.base.layouts[layout])
def rename_layout(self, layout, newname): def rename_layout(self, layout, newname):
"""Rename a layout""" """Rename a layout"""
if self.base.layouts.has_key(layout): if layout in self.base.layouts:
self.base.layouts[newname] = self.base.layouts[layout] self.base.layouts[newname] = self.base.layouts[layout]
del(self.base.layouts[layout]) del(self.base.layouts[layout])
def list_layouts(self): def list_layouts(self):
"""List all configured layouts""" """List all configured layouts"""
return(self.base.layouts.keys()) return(list(self.base.layouts.keys()))
def connect_gsetting_callbacks(self): def connect_gsetting_callbacks(self):
"""Get system settings and create callbacks for changes""" """Get system settings and create callbacks for changes"""
@ -416,7 +414,7 @@ class Config(object):
self.system_mono_font = None self.system_mono_font = None
# Need to trigger a reconfigure to change active terminals immediately # Need to trigger a reconfigure to change active terminals immediately
if "Terminator" not in globals(): if "Terminator" not in globals():
from terminator import Terminator from .terminator import Terminator
Terminator().reconfigure() Terminator().reconfigure()
def save(self): def save(self):
@ -490,7 +488,7 @@ class ConfigBase(Borg):
Borg.__init__(self, self.__class__.__name__) Borg.__init__(self, self.__class__.__name__)
self.prepare_attributes() self.prepare_attributes()
import optionparse from . import optionparse
self.command_line_options = optionparse.options self.command_line_options = optionparse.options
self.load() self.load()
@ -585,7 +583,7 @@ class ConfigBase(Borg):
configspec = ConfigObj(configspecdata) configspec = ConfigObj(configspecdata)
if DEBUG == True: if DEBUG == True:
configspec.write(open('/tmp/terminator_configspec_debug.txt', 'w')) configspec.write(open('/tmp/terminator_configspec_debug.txt', 'wb'))
return(configspec) return(configspec)
def load(self): def load(self):
@ -604,7 +602,7 @@ class ConfigBase(Borg):
dbg('looking for config file: %s' % filename) dbg('looking for config file: %s' % filename)
try: try:
configfile = open(filename, 'r') configfile = open(filename, 'r')
except Exception, ex: except Exception as ex:
if not self.whined: if not self.whined:
err('ConfigBase::load: Unable to open %s (%s)' % (filename, ex)) err('ConfigBase::load: Unable to open %s (%s)' % (filename, ex))
self.whined = True self.whined = True
@ -617,7 +615,7 @@ class ConfigBase(Borg):
parser = ConfigObj(configfile, configspec=configspec) parser = ConfigObj(configfile, configspec=configspec)
validator = Validator() validator = Validator()
result = parser.validate(validator, preserve_errors=True) result = parser.validate(validator, preserve_errors=True)
except Exception, ex: except Exception as ex:
err('Unable to load configuration: %s' % ex) err('Unable to load configuration: %s' % ex)
return return
@ -637,12 +635,12 @@ class ConfigBase(Borg):
if section_name == 'profiles': if section_name == 'profiles':
for profile in parser[section_name]: for profile in parser[section_name]:
dbg('ConfigBase::load: Processing profile: %s' % profile) dbg('ConfigBase::load: Processing profile: %s' % profile)
if not section.has_key(section_name): if section_name not in section:
# FIXME: Should this be outside the loop? # FIXME: Should this be outside the loop?
section[profile] = copy(DEFAULTS['profiles']['default']) section[profile] = copy(DEFAULTS['profiles']['default'])
section[profile].update(parser[section_name][profile]) section[profile].update(parser[section_name][profile])
elif section_name == 'plugins': elif section_name == 'plugins':
if not parser.has_key(section_name): if section_name not in parser:
continue continue
for part in parser[section_name]: for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name, dbg('ConfigBase::load: Processing %s: %s' % (section_name,
@ -657,7 +655,7 @@ class ConfigBase(Borg):
continue continue
section[layout] = parser[section_name][layout] section[layout] = parser[section_name][layout]
elif section_name == 'keybindings': elif section_name == 'keybindings':
if not parser.has_key(section_name): if section_name not in parser:
continue continue
for part in parser[section_name]: for part in parser[section_name]:
dbg('ConfigBase::load: Processing %s: %s' % (section_name, dbg('ConfigBase::load: Processing %s: %s' % (section_name,
@ -669,7 +667,7 @@ class ConfigBase(Borg):
else: else:
try: try:
section.update(parser[section_name]) section.update(parser[section_name])
except KeyError, ex: except KeyError as ex:
dbg('ConfigBase::load: skipping missing section %s' % dbg('ConfigBase::load: skipping missing section %s' %
section_name) section_name)
@ -683,7 +681,7 @@ class ConfigBase(Borg):
def save(self): def save(self):
"""Save the config to a file""" """Save the config to a file"""
dbg('ConfigBase::save: saving config') dbg('ConfigBase::save: saving config')
parser = ConfigObj() parser = ConfigObj(encoding='utf-8')
parser.indent_type = ' ' parser.indent_type = ' '
for section_name in ['global_config', 'keybindings']: for section_name in ['global_config', 'keybindings']:
@ -711,21 +709,26 @@ class ConfigBase(Borg):
if not os.path.isdir(config_dir): if not os.path.isdir(config_dir):
os.makedirs(config_dir) os.makedirs(config_dir)
try: try:
parser.write(open(self.command_line_options.config, 'w')) temp_file = self.command_line_options.config + '.tmp'
except Exception, ex:
with open(temp_file, 'wb') as fh:
parser.write(fh)
os.rename(temp_file, self.command_line_options.config)
except Exception as ex:
err('ConfigBase::save: Unable to save config: %s' % ex) err('ConfigBase::save: Unable to save config: %s' % ex)
def get_item(self, key, profile='default', plugin=None, default=None): def get_item(self, key, profile='default', plugin=None, default=None):
"""Look up a configuration item""" """Look up a configuration item"""
if not self.profiles.has_key(profile): if profile not in self.profiles:
# Hitting this generally implies a bug # Hitting this generally implies a bug
profile = 'default' profile = 'default'
if self.global_config.has_key(key): if key in self.global_config:
dbg('ConfigBase::get_item: %s found in globals: %s' % dbg('ConfigBase::get_item: %s found in globals: %s' %
(key, self.global_config[key])) (key, self.global_config[key]))
return(self.global_config[key]) return(self.global_config[key])
elif self.profiles[profile].has_key(key): elif key in self.profiles[profile]:
dbg('ConfigBase::get_item: %s found in profile %s: %s' % ( dbg('ConfigBase::get_item: %s found in profile %s: %s' % (
key, profile, self.profiles[profile][key])) key, profile, self.profiles[profile][key]))
return(self.profiles[profile][key]) return(self.profiles[profile][key])
@ -745,14 +748,14 @@ class ConfigBase(Borg):
dbg('ConfigBase::set_item: Setting %s=%s (profile=%s, plugin=%s)' % dbg('ConfigBase::set_item: Setting %s=%s (profile=%s, plugin=%s)' %
(key, value, profile, plugin)) (key, value, profile, plugin))
if self.global_config.has_key(key): if key in self.global_config:
self.global_config[key] = value self.global_config[key] = value
elif self.profiles[profile].has_key(key): elif key in self.profiles[profile]:
self.profiles[profile][key] = value self.profiles[profile][key] = value
elif key == 'keybindings': elif key == 'keybindings':
self.keybindings = value self.keybindings = value
elif plugin is not None: elif plugin is not None:
if not self.plugins.has_key(plugin): if plugin not in self.plugins:
self.plugins[plugin] = {} self.plugins[plugin] = {}
self.plugins[plugin][key] = value self.plugins[plugin][key] = value
else: else:
@ -762,7 +765,7 @@ class ConfigBase(Borg):
def get_plugin(self, plugin): def get_plugin(self, plugin):
"""Return a whole tree for a plugin""" """Return a whole tree for a plugin"""
if self.plugins.has_key(plugin): if plugin in self.plugins:
return(self.plugins[plugin]) return(self.plugins[plugin])
def set_plugin(self, plugin, tree): def set_plugin(self, plugin, tree):
@ -797,7 +800,7 @@ class ConfigBase(Borg):
def get_layout(self, layout): def get_layout(self, layout):
"""Return a layout""" """Return a layout"""
if self.layouts.has_key(layout): if layout in self.layouts:
return(self.layouts[layout]) return(self.layouts[layout])
else: else:
err('layout does not exist: %s' % layout) err('layout does not exist: %s' % layout)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

13
terminatorlib/container.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""container.py - classes necessary to contain Terminal widgets""" """container.py - classes necessary to contain Terminal widgets"""
@ -6,11 +5,11 @@
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
from factory import Factory from .factory import Factory
from config import Config from .config import Config
from util import dbg, err from .util import dbg, err
from translation import _ from .translation import _
from signalman import Signalman from .signalman import Signalman
# pylint: disable-msg=R0921 # pylint: disable-msg=R0921
class Container(object): class Container(object):
@ -283,7 +282,7 @@ the tab will also close all terminals within it.')
if mytype == 'Notebook': if mytype == 'Notebook':
labels = [] labels = []
last_active_term = [] last_active_term = []
for tabnum in xrange(0, self.get_n_pages()): for tabnum in range(0, self.get_n_pages()):
page = self.get_nth_page(tabnum) page = self.get_nth_page(tabnum)
label = self.get_tab_label(page) label = self.get_tab_label(page)
labels.append(label.get_custom_label()) labels.append(label.get_custom_label())

7
terminatorlib/cwd.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""cwd.py - function necessary to get the cwd for a given pid on various OSes """cwd.py - function necessary to get the cwd for a given pid on various OSes
@ -15,7 +14,7 @@
import platform import platform
import os import os
import pwd import pwd
from util import dbg, err from .util import dbg, err
try: try:
import psutil import psutil
@ -46,7 +45,7 @@ def get_pid_cwd():
func = linux_get_pid_cwd func = linux_get_pid_cwd
elif system == 'FreeBSD': elif system == 'FreeBSD':
try: try:
import freebsd from . import freebsd
func = freebsd.get_process_cwd func = freebsd.get_process_cwd
dbg('Using FreeBSD get_pid_cwd') dbg('Using FreeBSD get_pid_cwd')
except (OSError, NotImplementedError, ImportError): except (OSError, NotImplementedError, ImportError):
@ -66,7 +65,7 @@ def proc_get_pid_cwd(pid, path):
insert it into, e.g. /proc/%s/cwd""" insert it into, e.g. /proc/%s/cwd"""
try: try:
cwd = os.path.realpath(path % pid) cwd = os.path.realpath(path % pid)
except Exception, ex: except Exception as ex:
err('Unable to get cwd for PID %s: %s' % (pid, ex)) err('Unable to get cwd for PID %s: %s' % (pid, ex))
cwd = '/' cwd = '/'

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python2
#
# Copyright (c) 2008, Thomas Hurst <tom@hur.st> # Copyright (c) 2008, Thomas Hurst <tom@hur.st>
# #
# Use of this file is unrestricted provided this notice is retained. # Use of this file is unrestricted provided this notice is retained.
@ -10,7 +8,7 @@ from terminatorlib.version import APP_NAME, APP_VERSION
import socket import socket
import threading import threading
import SocketServer import socketserver
import code import code
import sys import sys
import readline import readline
@ -22,7 +20,7 @@ def ddbg(msg):
return return
dbg(msg) dbg(msg)
class PythonConsoleServer(SocketServer.BaseRequestHandler): class PythonConsoleServer(socketserver.BaseRequestHandler):
env = None env = None
def setup(self): def setup(self):
dbg('debugserver: connect from %s' % str(self.client_address)) dbg('debugserver: connect from %s' % str(self.client_address))
@ -165,7 +163,7 @@ class TerminatorConsole(code.InteractiveConsole):
def spawn(env): def spawn(env):
PythonConsoleServer.env = env PythonConsoleServer.env = env
tcpserver = SocketServer.TCPServer(('127.0.0.1', 0), PythonConsoleServer) tcpserver = socketserver.TCPServer(('127.0.0.1', 0), PythonConsoleServer)
dbg("debugserver: listening on %s" % str(tcpserver.server_address)) dbg("debugserver: listening on %s" % str(tcpserver.server_address))
debugserver = threading.Thread(target=tcpserver.serve_forever, name="DebugServer") debugserver = threading.Thread(target=tcpserver.serve_forever, name="DebugServer")
debugserver.setDaemon(True) debugserver.setDaemon(True)

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
# #
# Copyright (c) 2009, Emmanuel Bretelle <chantra@debuntu.org> # Copyright (c) 2009, Emmanuel Bretelle <chantra@debuntu.org>

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# TerminatorEncoding - charset encoding classes # TerminatorEncoding - charset encoding classes
# Copyright (C) 2006-2010 chantra@debuntu.org # Copyright (C) 2006-2010 chantra@debuntu.org
# #
@ -23,7 +22,7 @@ This list is taken from gnome-terminal's src/terminal-encoding.c
and src/encoding.c and src/encoding.c
""" """
from translation import _ from .translation import _
#pylint: disable-msg=R0903 #pylint: disable-msg=R0903
class TerminatorEncoding: class TerminatorEncoding:

17
terminatorlib/factory.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""factory.py - Maker of objects """factory.py - Maker of objects
@ -19,8 +18,8 @@ True
""" """
from borg import Borg from .borg import Borg
from util import dbg, err, inject_uuid from .util import dbg, err, inject_uuid
# pylint: disable-msg=R0201 # pylint: disable-msg=R0201
# pylint: disable-msg=W0613 # pylint: disable-msg=W0613
@ -33,7 +32,7 @@ class Factory(Borg):
'Notebook': 'notebook', 'Notebook': 'notebook',
'Container': 'container', 'Container': 'container',
'Window': 'window'} 'Window': 'window'}
types_keys = types.keys() types_keys = list(types.keys())
instance_types = {} instance_types = {}
instance_types_keys = [] instance_types_keys = []
@ -97,26 +96,26 @@ class Factory(Borg):
def make_window(self, **kwargs): def make_window(self, **kwargs):
"""Make a Window""" """Make a Window"""
import window from . import window
return(window.Window(**kwargs)) return(window.Window(**kwargs))
def make_terminal(self, **kwargs): def make_terminal(self, **kwargs):
"""Make a Terminal""" """Make a Terminal"""
import terminal from . import terminal
return(terminal.Terminal()) return(terminal.Terminal())
def make_hpaned(self, **kwargs): def make_hpaned(self, **kwargs):
"""Make an HPaned""" """Make an HPaned"""
import paned from . import paned
return(paned.HPaned()) return(paned.HPaned())
def make_vpaned(self, **kwargs): def make_vpaned(self, **kwargs):
"""Make a VPaned""" """Make a VPaned"""
import paned from . import paned
return(paned.VPaned()) return(paned.VPaned())
def make_notebook(self, **kwargs): def make_notebook(self, **kwargs):
"""Make a Notebook""" """Make a Notebook"""
import notebook from . import notebook
return(notebook.Notebook(kwargs['window'])) return(notebook.Notebook(kwargs['window']))

12
terminatorlib/freebsd.py Normal file → Executable file
View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
# #
# Copyright (c) 2008, Thomas Hurst <tom@hur.st> # Copyright (c) 2008, Thomas Hurst <tom@hur.st>
# #
@ -50,11 +50,11 @@ uintlen = c_size_t(sizeof(c_uint))
ver = c_uint(0) ver = c_uint(0)
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(uintlen), None, 0) < 0): if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(uintlen), None, 0) < 0):
raise OSError, "sysctlbyname returned < 0" raise OSError("sysctlbyname returned < 0")
# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions # kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions
if ver.value < 700104 and ver.value < 800019: if ver.value < 700104 and ver.value < 800019:
raise NotImplementedError, "cwd detection requires a recent 7.0-STABLE or 8-CURRENT" raise NotImplementedError("cwd detection requires a recent 7.0-STABLE or 8-CURRENT")
def get_process_cwd(pid): def get_process_cwd(pid):
@ -72,7 +72,7 @@ def get_process_cwd(pid):
return None return None
kifs = cast(buf, POINTER(kinfo_file)) kifs = cast(buf, POINTER(kinfo_file))
for i in xrange(0, uintlen.value / sizeof(kinfo_file)): for i in range(0, uintlen.value / sizeof(kinfo_file)):
kif = kifs[i] kif = kifs[i]
if kif.kf_fd == -1: # KF_FD_TYPE_CWD if kif.kf_fd == -1: # KF_FD_TYPE_CWD
return kif.kf_path return kif.kf_path
@ -80,12 +80,12 @@ def get_process_cwd(pid):
if __name__ == '__main__': if __name__ == '__main__':
import os, sys import os, sys
print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())) print(" => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid())))
for pid in sys.argv: for pid in sys.argv:
try: try:
pid = int(pid) pid = int(pid)
except: except:
pass pass
else: else:
print " => %d cwd = %s" % (pid, get_process_cwd(pid)) print(" => %d cwd = %s" % (pid, get_process_cwd(pid)))

View File

@ -1,17 +1,17 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""ipc.py - DBus server and API calls""" """ipc.py - DBus server and API calls"""
import hashlib
from gi.repository import Gdk from gi.repository import Gdk
import dbus.service import dbus.service
from dbus.exceptions import DBusException from dbus.exceptions import DBusException
import dbus.glib import dbus.glib
from borg import Borg from .borg import Borg
from terminator import Terminator from .terminator import Terminator
from config import Config from .config import Config
from factory import Factory from .factory import Factory
from util import dbg, enumerate_descendants from .util import dbg, enumerate_descendants
CONFIG = Config() CONFIG = Config()
if not CONFIG['dbus']: if not CONFIG['dbus']:
@ -23,7 +23,9 @@ BUS_BASE = 'net.tenshu.Terminator2'
BUS_PATH = '/net/tenshu/Terminator2' BUS_PATH = '/net/tenshu/Terminator2'
try: try:
# Try and include the X11 display name in the dbus bus name # Try and include the X11 display name in the dbus bus name
DISPLAY = hex(hash(Gdk.get_display().partition('.')[0])) DISPLAY = Gdk.get_display().partition('.')[0]
# In Python 3, hash() uses a different seed on each run, so use hashlib
DISPLAY = hashlib.md5(DISPLAY.encode('utf-8')).hexdigest()
BUS_NAME = '%s%s' % (BUS_BASE, DISPLAY) BUS_NAME = '%s%s' % (BUS_BASE, DISPLAY)
except: except:
BUS_NAME = BUS_BASE BUS_NAME = BUS_BASE
@ -185,7 +187,7 @@ class DBusService(Borg, dbus.service.Object):
def with_proxy(func): def with_proxy(func):
"""Decorator function to connect to the session dbus bus""" """Decorator function to connect to the session dbus bus"""
dbg('dbus client call: %s' % func.func_name) dbg('dbus client call: %s' % func.__name__)
def _exec(*args, **argd): def _exec(*args, **argd):
bus = dbus.SessionBus() bus = dbus.SessionBus()
proxy = bus.get_object(BUS_NAME, BUS_PATH) proxy = bus.get_object(BUS_NAME, BUS_PATH)
@ -205,45 +207,45 @@ def new_tab_cmdline(session, options):
@with_proxy @with_proxy
def new_window(session, options): def new_window(session, options):
"""Call the dbus method to open a new window""" """Call the dbus method to open a new window"""
print session.new_window() print(session.new_window())
@with_proxy @with_proxy
def new_tab(session, uuid, options): def new_tab(session, uuid, options):
"""Call the dbus method to open a new tab in the first window""" """Call the dbus method to open a new tab in the first window"""
print session.new_tab(uuid) print(session.new_tab(uuid))
@with_proxy @with_proxy
def hsplit(session, uuid, options): def hsplit(session, uuid, options):
"""Call the dbus method to horizontally split a terminal""" """Call the dbus method to horizontally split a terminal"""
print session.hsplit(uuid) print(session.hsplit(uuid))
@with_proxy @with_proxy
def vsplit(session, uuid, options): def vsplit(session, uuid, options):
"""Call the dbus method to vertically split a terminal""" """Call the dbus method to vertically split a terminal"""
print session.vsplit(uuid) print(session.vsplit(uuid))
@with_proxy @with_proxy
def get_terminals(session, options): def get_terminals(session, options):
"""Call the dbus method to return a list of all terminals""" """Call the dbus method to return a list of all terminals"""
print '\n'.join(session.get_terminals()) print('\n'.join(session.get_terminals()))
@with_proxy @with_proxy
def get_window(session, uuid, options): def get_window(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal""" """Call the dbus method to return the toplevel tab for a terminal"""
print session.get_window(uuid) print(session.get_window(uuid))
@with_proxy @with_proxy
def get_window_title(session, uuid, options): def get_window_title(session, uuid, options):
"""Call the dbus method to return the title of a tab""" """Call the dbus method to return the title of a tab"""
print session.get_window_title(uuid) print(session.get_window_title(uuid))
@with_proxy @with_proxy
def get_tab(session, uuid, options): def get_tab(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal""" """Call the dbus method to return the toplevel tab for a terminal"""
print session.get_tab(uuid) print(session.get_tab(uuid))
@with_proxy @with_proxy
def get_tab_title(session, uuid, options): def get_tab_title(session, uuid, options):
"""Call the dbus method to return the title of a tab""" """Call the dbus method to return the title of a tab"""
print session.get_tab_title(uuid) print(session.get_tab_title(uuid))

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window # Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -24,7 +23,7 @@ keyboard shortcuts.
import re import re
from gi.repository import Gtk, Gdk from gi.repository import Gtk, Gdk
from util import err from .util import err
class KeymapError(Exception): class KeymapError(Exception):
"""Custom exception for errors in keybinding configurations""" """Custom exception for errors in keybinding configurations"""
@ -61,7 +60,7 @@ class Keybindings:
"""Parse bindings and mangle into an appropriate form""" """Parse bindings and mangle into an appropriate form"""
self._lookup = {} self._lookup = {}
self._masks = 0 self._masks = 0
for action, bindings in self.keys.items(): for action, bindings in list(self.keys.items()):
if not isinstance(bindings, tuple): if not isinstance(bindings, tuple):
bindings = (bindings,) bindings = (bindings,)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""layoutlauncher.py - class for the Layout Launcher window""" """layoutlauncher.py - class for the Layout Launcher window"""
@ -7,11 +7,11 @@ import os
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import GObject from gi.repository import GObject
from util import dbg, err, spawn_new_terminator from .util import dbg, err, spawn_new_terminator
import config from . import config
from translation import _ from .translation import _
from terminator import Terminator from .terminator import Terminator
from plugin import PluginRegistry from .plugin import PluginRegistry
class LayoutLauncher: class LayoutLauncher:
"""Class implementing the various parts of the preferences editor""" """Class implementing the various parts of the preferences editor"""
@ -38,9 +38,9 @@ class LayoutLauncher:
librarypath = os.path.join(head, 'layoutlauncher.glade') librarypath = os.path.join(head, 'layoutlauncher.glade')
gladefile = open(librarypath, 'r') gladefile = open(librarypath, 'r')
gladedata = gladefile.read() gladedata = gladefile.read()
except Exception, ex: except Exception as ex:
print "Failed to find layoutlauncher.glade" print("Failed to find layoutlauncher.glade")
print ex print(ex)
return return
self.builder.add_from_string(gladedata) self.builder.add_from_string(gladedata)
@ -72,7 +72,7 @@ class LayoutLauncher:
"""Update the contents of the layout""" """Update the contents of the layout"""
self.layouttreestore.clear() self.layouttreestore.clear()
layouts = self.config.list_layouts() layouts = self.config.list_layouts()
for layout in sorted(layouts, cmp=lambda x,y: cmp(x.lower(), y.lower())): for layout in sorted(layouts, key=str.lower):
if layout != "default": if layout != "default":
self.layouttreestore.append([layout]) self.layouttreestore.append([layout])
else: else:
@ -100,9 +100,9 @@ class LayoutLauncher:
spawn_new_terminator(self.terminator.origcwd, ['-u', '-l', layout]) spawn_new_terminator(self.terminator.origcwd, ['-u', '-l', layout])
if __name__ == '__main__': if __name__ == '__main__':
import util from . import util
util.DEBUG = True util.DEBUG = True
import terminal from . import terminal
LAYOUTLAUNCHER = LayoutLauncher() LAYOUTLAUNCHER = LayoutLauncher()
Gtk.main() Gtk.main()

44
terminatorlib/notebook.py Executable file → Normal file
View File

@ -1,20 +1,20 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""notebook.py - classes for the notebook widget""" """notebook.py - classes for the notebook widget"""
from functools import cmp_to_key
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Gdk from gi.repository import Gdk
from gi.repository import Gio from gi.repository import Gio
from terminator import Terminator from .terminator import Terminator
from config import Config from .config import Config
from factory import Factory from .factory import Factory
from container import Container from .container import Container
from editablelabel import EditableLabel from .editablelabel import EditableLabel
from translation import _ from .translation import _
from util import err, dbg, enumerate_descendants, make_uuid from .util import err, dbg, enumerate_descendants, make_uuid
class Notebook(Container, Gtk.Notebook): class Notebook(Container, Gtk.Notebook):
"""Class implementing a Gtk.Notebook container""" """Class implementing a Gtk.Notebook container"""
@ -65,7 +65,7 @@ class Notebook(Container, Gtk.Notebook):
pos = getattr(Gtk.PositionType, self.config['tab_position'].upper()) pos = getattr(Gtk.PositionType, self.config['tab_position'].upper())
self.set_tab_pos(pos) self.set_tab_pos(pos)
for tab in xrange(0, self.get_n_pages()): for tab in range(0, self.get_n_pages()):
label = self.get_tab_label(self.get_nth_page(tab)) label = self.get_tab_label(self.get_nth_page(tab))
label.update_angle() label.update_angle()
@ -88,7 +88,7 @@ class Notebook(Container, Gtk.Notebook):
if (order_a > order_b): if (order_a > order_b):
return 1 return 1
if not layout.has_key('children'): if 'children' not in layout:
err('layout specifies no children: %s' % layout) err('layout specifies no children: %s' % layout)
return return
@ -99,8 +99,8 @@ class Notebook(Container, Gtk.Notebook):
return return
num = 0 num = 0
keys = children.keys() keys = list(children.keys())
keys.sort(child_compare) keys = sorted(keys, key=cmp_to_key(child_compare))
for child_key in keys: for child_key in keys:
child = children[child_key] child = children[child_key]
@ -122,7 +122,7 @@ class Notebook(Container, Gtk.Notebook):
# This page does not yet exist, so make it # This page does not yet exist, so make it
self.newtab(children[child_key]) self.newtab(children[child_key])
page = self.get_nth_page(num) page = self.get_nth_page(num)
if layout.has_key('labels'): if 'labels' in layout:
labeltext = layout['labels'][num] labeltext = layout['labels'][num]
if labeltext and labeltext != "None": if labeltext and labeltext != "None":
label = self.get_tab_label(page) label = self.get_tab_label(page)
@ -133,7 +133,7 @@ class Notebook(Container, Gtk.Notebook):
self.last_active_term[page] = make_uuid(layout['last_active_term'][num]) self.last_active_term[page] = make_uuid(layout['last_active_term'][num])
num = num + 1 num = num + 1
if layout.has_key('active_page'): if 'active_page' in layout:
# Need to do it later, or layout changes result # Need to do it later, or layout changes result
GObject.idle_add(self.set_current_page, int(layout['active_page'])) GObject.idle_add(self.set_current_page, int(layout['active_page']))
else: else:
@ -233,7 +233,7 @@ class Notebook(Container, Gtk.Notebook):
def get_children(self): def get_children(self):
"""Return an ordered list of our children""" """Return an ordered list of our children"""
children = [] children = []
for page in xrange(0,self.get_n_pages()): for page in range(0,self.get_n_pages()):
children.append(self.get_nth_page(page)) children.append(self.get_nth_page(page))
return(children) return(children)
@ -278,13 +278,13 @@ class Notebook(Container, Gtk.Notebook):
handler = handler[0] handler = handler[0]
self.connect_child(widget, signal, handler, *args) self.connect_child(widget, signal, handler, *args)
if metadata and metadata.has_key('tabnum'): if metadata and 'tabnum' in metadata:
tabpos = metadata['tabnum'] tabpos = metadata['tabnum']
else: else:
tabpos = -1 tabpos = -1
label = TabLabel(self.window.get_title(), self) label = TabLabel(self.window.get_title(), self)
if metadata and metadata.has_key('label'): if metadata and 'label' in metadata:
dbg('creating TabLabel with text: %s' % metadata['label']) dbg('creating TabLabel with text: %s' % metadata['label'])
label.set_custom_label(metadata['label']) label.set_custom_label(metadata['label'])
label.connect('close-clicked', self.closetab) label.connect('close-clicked', self.closetab)
@ -334,7 +334,7 @@ class Notebook(Container, Gtk.Notebook):
err('TabLabel::closetab: called on non-Notebook: %s' % widget) err('TabLabel::closetab: called on non-Notebook: %s' % widget)
return return
for i in xrange(0, nb.get_n_pages() + 1): for i in range(0, nb.get_n_pages() + 1):
if label == nb.get_tab_label(nb.get_nth_page(i)): if label == nb.get_tab_label(nb.get_nth_page(i)):
tabnum = i tabnum = i
break break
@ -434,7 +434,7 @@ class Notebook(Container, Gtk.Notebook):
del(self) del(self)
# Find the last terminal in the new parent and give it focus # Find the last terminal in the new parent and give it focus
terms = parent.get_visible_terminals() terms = parent.get_visible_terminals()
terms.keys()[-1].grab_focus() list(terms.keys())[-1].grab_focus()
def page_num_descendant(self, widget): def page_num_descendant(self, widget):
"""Find the tabnum of the tab containing a widget at any level""" """Find the tabnum of the tab containing a widget at any level"""
@ -464,7 +464,7 @@ class Notebook(Container, Gtk.Notebook):
if self.terminator.doing_layout == True: if self.terminator.doing_layout == True:
return return
last_active_term = {} last_active_term = {}
for tabnum in xrange(0, self.get_n_pages()): for tabnum in range(0, self.get_n_pages()):
nth_page = self.get_nth_page(tabnum) nth_page = self.get_nth_page(tabnum)
if nth_page in self.last_active_term: if nth_page in self.last_active_term:
last_active_term[nth_page] = self.last_active_term[nth_page] last_active_term[nth_page] = self.last_active_term[nth_page]
@ -501,7 +501,7 @@ class Notebook(Container, Gtk.Notebook):
#print "event: %s" % event #print "event: %s" % event
child = self.get_nth_page(self.get_current_page()) child = self.get_nth_page(self.get_current_page())
if child == None: if child == None:
print "Child = None, return false" print("Child = None, return false")
return False return False
event_widget = Gtk.get_event_widget(event) event_widget = Gtk.get_event_widget(event)
@ -509,7 +509,7 @@ class Notebook(Container, Gtk.Notebook):
if event_widget == None or \ if event_widget == None or \
event_widget == child or \ event_widget == child or \
event_widget.is_ancestor(child): event_widget.is_ancestor(child):
print "event_widget is wrong one, return false" print("event_widget is wrong one, return false")
return False return False
# Not sure if we need these. I don't think wehave any action widgets # Not sure if we need these. I don't think wehave any action widgets

13
terminatorlib/optionparse.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator.optionparse - Parse commandline options # Terminator.optionparse - Parse commandline options
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -20,11 +19,11 @@ import sys
import os import os
from optparse import OptionParser, SUPPRESS_HELP from optparse import OptionParser, SUPPRESS_HELP
from util import dbg, err from .util import dbg, err
import util from . import util
import config from . import config
import version from . import version
from translation import _ from .translation import _
options = None options = None
@ -110,7 +109,7 @@ icon for the window (by file or name)'))
parser.error('Additional unexpected arguments found: %s' % args) parser.error('Additional unexpected arguments found: %s' % args)
if options.version: if options.version:
print '%s %s' % (version.APP_NAME, version.APP_VERSION) print('%s %s' % (version.APP_NAME, version.APP_VERSION))
sys.exit(0) sys.exit(0)
if options.debug_classes or options.debug_methods: if options.debug_classes or options.debug_methods:

19
terminatorlib/paned.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""paned.py - a base Paned container class and the vertical/horizontal """paned.py - a base Paned container class and the vertical/horizontal
@ -7,10 +6,10 @@ variants"""
import time import time
from gi.repository import GObject, Gtk, Gdk from gi.repository import GObject, Gtk, Gdk
from util import dbg, err, enumerate_descendants from .util import dbg, err, enumerate_descendants
from terminator import Terminator from .terminator import Terminator
from factory import Factory from .factory import Factory
from container import Container from .container import Container
# pylint: disable-msg=R0921 # pylint: disable-msg=R0921
# pylint: disable-msg=E1101 # pylint: disable-msg=E1101
@ -123,7 +122,7 @@ class Paned(Container):
self.connect_child(widget, signal, handler, *args) self.connect_child(widget, signal, handler, *args)
if metadata and \ if metadata and \
metadata.has_key('had_focus') and \ 'had_focus' in metadata and \
metadata['had_focus'] == True: metadata['had_focus'] == True:
widget.grab_focus() widget.grab_focus()
@ -357,7 +356,7 @@ class Paned(Container):
def create_layout(self, layout): def create_layout(self, layout):
"""Apply layout configuration""" """Apply layout configuration"""
if not layout.has_key('children'): if 'children' not in layout:
err('layout specifies no children: %s' % layout) err('layout specifies no children: %s' % layout)
return return
@ -376,14 +375,14 @@ class Paned(Container):
for child in children: for child in children:
key = children[child]['order'] key = children[child]['order']
child_order_map[key] = child child_order_map[key] = child
map_keys = child_order_map.keys() map_keys = list(child_order_map.keys())
map_keys.sort() map_keys.sort()
for map_key in map_keys: for map_key in map_keys:
keys.append(child_order_map[map_key]) keys.append(child_order_map[map_key])
except KeyError: except KeyError:
# We've failed to figure out the order. At least give the terminals # We've failed to figure out the order. At least give the terminals
# in the wrong order # in the wrong order
keys = children.keys() keys = list(children.keys())
num = 0 num = 0
for child_key in keys: for child_key in keys:
@ -411,7 +410,7 @@ class Paned(Container):
self.get_child2().create_layout(children[keys[1]]) self.get_child2().create_layout(children[keys[1]])
# Set the position with ratio. For some reason more reliable than by pos. # Set the position with ratio. For some reason more reliable than by pos.
if layout.has_key('ratio'): if 'ratio' in layout:
self.ratio = float(layout['ratio']) self.ratio = float(layout['ratio'])
self.set_position_by_ratio() self.set_position_by_ratio()

17
terminatorlib/plugin.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""plugin.py - Base plugin system """plugin.py - Base plugin system
@ -25,10 +24,10 @@
import sys import sys
import os import os
import borg from . import borg
from config import Config from .config import Config
from util import dbg, err, get_config_dir from .util import dbg, err, get_config_dir
from terminator import Terminator from .terminator import Terminator
class Plugin(object): class Plugin(object):
"""Definition of our base plugin class""" """Definition of our base plugin class"""
@ -95,7 +94,7 @@ class PluginRegistry(borg.Borg):
try: try:
module = __import__(plugin[:-3], None, None, ['']) module = __import__(plugin[:-3], None, None, [''])
for item in getattr(module, 'AVAILABLE'): for item in getattr(module, 'AVAILABLE'):
if item not in self.available_plugins.keys(): if item not in list(self.available_plugins.keys()):
func = getattr(module, item) func = getattr(module, item)
self.available_plugins[item] = func self.available_plugins[item] = func
@ -104,7 +103,7 @@ class PluginRegistry(borg.Borg):
continue continue
if item not in self.instances: if item not in self.instances:
self.instances[item] = func() self.instances[item] = func()
except Exception, ex: except Exception as ex:
err('PluginRegistry::load_plugins: Importing plugin %s \ err('PluginRegistry::load_plugins: Importing plugin %s \
failed: %s' % (plugin, ex)) failed: %s' % (plugin, ex))
@ -127,12 +126,12 @@ for %s' % (len(self.instances), capability))
def get_available_plugins(self): def get_available_plugins(self):
"""Return a list of all available plugins whether they are enabled or """Return a list of all available plugins whether they are enabled or
disabled""" disabled"""
return(self.available_plugins.keys()) return(list(self.available_plugins.keys()))
def is_enabled(self, plugin): def is_enabled(self, plugin):
"""Return a boolean value indicating whether a plugin is enabled or """Return a boolean value indicating whether a plugin is enabled or
not""" not"""
return(self.instances.has_key(plugin)) return(plugin in self.instances)
def enable(self, plugin): def enable(self, plugin):
"""Enable a plugin""" """Enable a plugin"""

9
terminatorlib/plugins/activitywatch.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""activitywatch.py - Terminator Plugin to watch a terminal for activity""" """activitywatch.py - Terminator Plugin to watch a terminal for activity"""
@ -53,7 +52,7 @@ class ActivityWatch(plugin.MenuItem):
def callback(self, menuitems, menu, terminal): def callback(self, menuitems, menu, terminal):
"""Add our menu item to the menu""" """Add our menu item to the menu"""
item = Gtk.CheckMenuItem.new_with_mnemonic(_('Watch for _activity')) item = Gtk.CheckMenuItem.new_with_mnemonic(_('Watch for _activity'))
item.set_active(self.watches.has_key(terminal)) item.set_active(terminal in self.watches)
if item.get_active(): if item.get_active():
item.connect("activate", self.unwatch, terminal) item.connect("activate", self.unwatch, terminal)
else: else:
@ -85,7 +84,7 @@ class ActivityWatch(plugin.MenuItem):
terminal.get_window_title(), 'terminator') terminal.get_window_title(), 'terminator')
this_time = time.mktime(time.gmtime()) this_time = time.mktime(time.gmtime())
if not self.last_notifies.has_key(terminal): if terminal not in self.last_notifies:
show_notify = True show_notify = True
else: else:
last_time = self.last_notifies[terminal] last_time = self.last_notifies[terminal]
@ -119,7 +118,7 @@ class InactivityWatch(plugin.MenuItem):
def callback(self, menuitems, menu, terminal): def callback(self, menuitems, menu, terminal):
"""Add our menu item to the menu""" """Add our menu item to the menu"""
item = Gtk.CheckMenuItem.new_with_mnemonic(_("Watch for _silence")) item = Gtk.CheckMenuItem.new_with_mnemonic(_("Watch for _silence"))
item.set_active(self.watches.has_key(terminal)) item.set_active(terminal in self.watches)
if item.get_active(): if item.get_active():
item.connect("activate", self.unwatch, terminal) item.connect("activate", self.unwatch, terminal)
else: else:
@ -153,7 +152,7 @@ class InactivityWatch(plugin.MenuItem):
def check_times(self, terminal): def check_times(self, terminal):
"""Check if this terminal has gone silent""" """Check if this terminal has gone silent"""
time_now = time.mktime(time.gmtime()) time_now = time.mktime(time.gmtime())
if not self.last_activities.has_key(terminal): if terminal not in self.last_activities:
dbg('Terminal %s has no last activity' % terminal) dbg('Terminal %s has no last activity' % terminal)
return True return True

11
terminatorlib/plugins/custom_commands.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""custom_commands.py - Terminator Plugin to add custom command menu entries""" """custom_commands.py - Terminator Plugin to add custom command menu entries"""
@ -16,7 +15,7 @@ from terminatorlib.config import Config
from terminatorlib.translation import _ from terminatorlib.translation import _
from terminatorlib.util import get_config_dir, err, dbg, gerr from terminatorlib.util import get_config_dir, err, dbg, gerr
(CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = range(0,3) (CC_COL_ENABLED, CC_COL_NAME, CC_COL_COMMAND) = list(range(0,3))
# Every plugin you want Terminator to load *must* be listed in 'AVAILABLE' # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
AVAILABLE = ['CustomCommandsMenu'] AVAILABLE = ['CustomCommandsMenu']
@ -35,13 +34,13 @@ class CustomCommandsMenu(plugin.MenuItem):
noord_cmds = [] noord_cmds = []
for part in sections: for part in sections:
s = sections[part] s = sections[part]
if not (s.has_key("name") and s.has_key("command")): if not ("name" in s and "command" in s):
print "CustomCommandsMenu: Ignoring section %s" % s print("CustomCommandsMenu: Ignoring section %s" % s)
continue continue
name = s["name"] name = s["name"]
command = s["command"] command = s["command"]
enabled = s["enabled"] and s["enabled"] or False enabled = s["enabled"] and s["enabled"] or False
if s.has_key("position"): if "position" in s:
self.cmd_list[int(s["position"])] = {'enabled' : enabled, self.cmd_list[int(s["position"])] = {'enabled' : enabled,
'name' : name, 'name' : name,
'command' : command 'command' : command
@ -127,7 +126,7 @@ class CustomCommandsMenu(plugin.MenuItem):
if command[-1] != '\n': if command[-1] != '\n':
command = command + '\n' command = command + '\n'
for terminal in data['terminals']: for terminal in data['terminals']:
terminal.vte.feed_child(command, len(command)) terminal.vte.feed_child_binary(command.encode(terminal.vte.get_encoding()))
def configure(self, widget, data = None): def configure(self, widget, data = None):
ui = {} ui = {}

View File

@ -1,5 +1,3 @@
#!/usr/bin/env python2
# Plugin by Sinan Nalkaya <sardok@gmail.com> # Plugin by Sinan Nalkaya <sardok@gmail.com>
# See LICENSE of Terminator package. # See LICENSE of Terminator package.
@ -30,7 +28,7 @@ class Logger(plugin.MenuItem):
def callback(self, menuitems, menu, terminal): def callback(self, menuitems, menu, terminal):
""" Add save menu item to the menu""" """ Add save menu item to the menu"""
vte_terminal = terminal.get_vte() vte_terminal = terminal.get_vte()
if not self.loggers.has_key(vte_terminal): if vte_terminal not in self.loggers:
item = Gtk.MenuItem.new_with_mnemonic(_('Start _Logger')) item = Gtk.MenuItem.new_with_mnemonic(_('Start _Logger'))
item.connect("activate", self.start_logger, terminal) item.connect("activate", self.start_logger, terminal)
else: else:

2
terminatorlib/plugins/maven.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Copyright (c) 2010 Julien Nicoulaud <julien.nicoulaud@gmail.com> # Copyright (c) 2010 Julien Nicoulaud <julien.nicoulaud@gmail.com>
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -14,6 +13,7 @@
# 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 # Foundation, Inc., 51 Franklin Street, Fifth Floor
# , Boston, MA 02110-1301 USA # , Boston, MA 02110-1301 USA
import re import re
import terminatorlib.plugin as plugin import terminatorlib.plugin as plugin

1
terminatorlib/plugins/terminalshot.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""terminalshot.py - Terminator Plugin to take 'screenshots' of individual """terminalshot.py - Terminator Plugin to take 'screenshots' of individual

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
import terminatorlib.plugin as plugin import terminatorlib.plugin as plugin
# AVAILABLE must contain a list of all the classes that you want exposed # AVAILABLE must contain a list of all the classes that you want exposed

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net? # Terminator by Chris Jones <cmsj@tenshu.net?
# GPL v2 only # GPL v2 only
"""url_handlers.py - Default plugins for URL handling""" """url_handlers.py - Default plugins for URL handling"""

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
"""Preferences Editor for Terminator. """Preferences Editor for Terminator.
Load a UIBuilder config file, display it, Load a UIBuilder config file, display it,
@ -10,14 +10,14 @@ write it to a config file
import os import os
from gi.repository import GObject, Gtk, Gdk from gi.repository import GObject, Gtk, Gdk
from util import dbg, err from .util import dbg, err
import config from . import config
from keybindings import Keybindings, KeymapError from .keybindings import Keybindings, KeymapError
from translation import _ from .translation import _
from encoding import TerminatorEncoding from .encoding import TerminatorEncoding
from terminator import Terminator from .terminator import Terminator
from plugin import PluginRegistry from .plugin import PluginRegistry
from version import APP_NAME from .version import APP_NAME
def color2hex(widget): def color2hex(widget):
"""Pull the colour values out of a Gtk ColorPicker widget and return them """Pull the colour values out of a Gtk ColorPicker widget and return them
@ -184,9 +184,9 @@ class PrefsEditor:
librarypath = os.path.join(head, 'preferences.glade') librarypath = os.path.join(head, 'preferences.glade')
gladefile = open(librarypath, 'r') gladefile = open(librarypath, 'r')
gladedata = gladefile.read() gladedata = gladefile.read()
except Exception, ex: except Exception as ex:
print "Failed to find preferences.glade" print("Failed to find preferences.glade")
print ex print(ex)
return return
self.builder.add_from_string(gladedata) self.builder.add_from_string(gladedata)
@ -207,7 +207,7 @@ class PrefsEditor:
try: try:
self.config.inhibit_save() self.config.inhibit_save()
self.set_values() self.set_values()
except Exception, e: except Exception as e:
err('Unable to set values: %s' % e) err('Unable to set values: %s' % e)
self.config.uninhibit_save() self.config.uninhibit_save()
@ -564,7 +564,7 @@ class PrefsEditor:
# NOTE: The palette selector is set after the colour pickers # NOTE: The palette selector is set after the colour pickers
# Palette colour pickers # Palette colour pickers
colourpalette = self.config['palette'].split(':') colourpalette = self.config['palette'].split(':')
for i in xrange(1, 17): for i in range(1, 17):
widget = guiget('palette_colorpicker_%d' % i) widget = guiget('palette_colorpicker_%d' % i)
widget.set_color(Gdk.color_parse(colourpalette[i - 1])) widget.set_color(Gdk.color_parse(colourpalette[i - 1]))
# Now set the palette selector widget # Now set the palette selector widget
@ -652,7 +652,7 @@ class PrefsEditor:
encodingstore = guiget('EncodingListStore') encodingstore = guiget('EncodingListStore')
value = self.config['encoding'] value = self.config['encoding']
encodings = TerminatorEncoding().get_list() encodings = TerminatorEncoding().get_list()
encodings.sort(lambda x, y: cmp(x[2].lower(), y[2].lower())) encodings.sort(key=lambda x: x[2].lower())
for encoding in encodings: for encoding in encodings:
if encoding[1] is None: if encoding[1] is None:
@ -890,7 +890,7 @@ class PrefsEditor:
guiget = self.builder.get_object guiget = self.builder.get_object
active = widget.get_active() active = widget.get_active()
for key in self.palettevalues.keys(): for key in list(self.palettevalues.keys()):
if self.palettevalues[key] == active: if self.palettevalues[key] == active:
value = key value = key
@ -899,20 +899,20 @@ class PrefsEditor:
else: else:
sensitive = False sensitive = False
for num in xrange(1, 17): for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num) picker = guiget('palette_colorpicker_%d' % num)
picker.set_sensitive(sensitive) picker.set_sensitive(sensitive)
if value in self.palettes: if value in self.palettes:
palette = self.palettes[value] palette = self.palettes[value]
palettebits = palette.split(':') palettebits = palette.split(':')
for num in xrange(1, 17): for num in range(1, 17):
# Update the visible elements # Update the visible elements
picker = guiget('palette_colorpicker_%d' % num) picker = guiget('palette_colorpicker_%d' % num)
picker.set_color(Gdk.color_parse(palettebits[num - 1])) picker.set_color(Gdk.color_parse(palettebits[num - 1]))
elif value == 'custom': elif value == 'custom':
palettebits = [] palettebits = []
for num in xrange(1, 17): for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num) picker = guiget('palette_colorpicker_%d' % num)
palettebits.append(color2hex(picker)) palettebits.append(color2hex(picker))
palette = ':'.join(palettebits) palette = ':'.join(palettebits)
@ -940,7 +940,7 @@ class PrefsEditor:
guiget = self.builder.get_object guiget = self.builder.get_object
# FIXME: We do this at least once elsewhere. refactor! # FIXME: We do this at least once elsewhere. refactor!
for num in xrange(1, 17): for num in range(1, 17):
picker = guiget('palette_colorpicker_%d' % num) picker = guiget('palette_colorpicker_%d' % num)
value = color2hex(picker) value = color2hex(picker)
palettebits.append(value) palettebits.append(value)
@ -1449,7 +1449,7 @@ class PrefsEditor:
guiget = self.builder.get_object guiget = self.builder.get_object
active = widget.get_active() active = widget.get_active()
for key in self.colorschemevalues.keys(): for key in list(self.colorschemevalues.keys()):
if self.colorschemevalues[key] == active: if self.colorschemevalues[key] == active:
value = key value = key
@ -1554,7 +1554,7 @@ class LayoutEditor:
listitems = {} listitems = {}
store.clear() store.clear()
children = layout.keys() children = list(layout.keys())
i = 0 i = 0
while children != []: while children != []:
child = children.pop() child = children.pop()
@ -1650,17 +1650,17 @@ class LayoutEditor:
command.set_sensitive(True) command.set_sensitive(True)
chooser.set_sensitive(True) chooser.set_sensitive(True)
workdir.set_sensitive(True) workdir.set_sensitive(True)
if layout_item.has_key('command') and layout_item['command'] != '': if 'command' in layout_item and layout_item['command'] != '':
command.set_text(layout_item['command']) command.set_text(layout_item['command'])
else: else:
command.set_text('') command.set_text('')
if layout_item.has_key('profile') and layout_item['profile'] != '': if 'profile' in layout_item and layout_item['profile'] != '':
chooser.set_active(self.profile_profile_to_ids[layout_item['profile']]) chooser.set_active(self.profile_profile_to_ids[layout_item['profile']])
else: else:
chooser.set_active(0) chooser.set_active(0)
if layout_item.has_key('directory') and layout_item['directory'] != '': if 'directory' in layout_item and layout_item['directory'] != '':
workdir.set_text(layout_item['directory']) workdir.set_text(layout_item['directory'])
else: else:
workdir.set_text('') workdir.set_text('')
@ -1689,9 +1689,9 @@ class LayoutEditor:
self.config.save() self.config.save()
if __name__ == '__main__': if __name__ == '__main__':
import util from . import util
util.DEBUG = True util.DEBUG = True
import terminal from . import terminal
TERM = terminal.Terminal() TERM = terminal.Terminal()
PREFEDIT = PrefsEditor(TERM) PREFEDIT = PrefsEditor(TERM)

0
terminatorlib/pylint.sh Executable file → Normal file
View File

5
terminatorlib/searchbar.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""searchbar.py - classes necessary to provide a terminal search bar""" """searchbar.py - classes necessary to provide a terminal search bar"""
@ -7,8 +6,8 @@ from gi.repository import Gtk, Gdk
from gi.repository import GObject from gi.repository import GObject
from gi.repository import GLib from gi.repository import GLib
from translation import _ from .translation import _
from config import Config from .config import Config
# pylint: disable-msg=R0904 # pylint: disable-msg=R0904
class Searchbar(Gtk.HBox): class Searchbar(Gtk.HBox):

21
terminatorlib/signalman.py Executable file → Normal file
View File

@ -1,9 +1,8 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""Simple management of Gtk Widget signal handlers""" """Simple management of Gtk Widget signal handlers"""
from util import dbg, err from .util import dbg, err
class Signalman(object): class Signalman(object):
"""Class providing glib signal tracking and management""" """Class providing glib signal tracking and management"""
@ -16,16 +15,16 @@ class Signalman(object):
def __del__(self): def __del__(self):
"""Class destructor. This is only used to check for stray signals""" """Class destructor. This is only used to check for stray signals"""
if len(self.cnxids.keys()) > 0: if len(list(self.cnxids.keys())) > 0:
dbg('Remaining signals: %s' % self.cnxids) dbg('Remaining signals: %s' % self.cnxids)
def new(self, widget, signal, handler, *args): def new(self, widget, signal, handler, *args):
"""Register a new signal on a widget""" """Register a new signal on a widget"""
if not self.cnxids.has_key(widget): if widget not in self.cnxids:
dbg('creating new bucket for %s' % type(widget)) dbg('creating new bucket for %s' % type(widget))
self.cnxids[widget] = {} self.cnxids[widget] = {}
if self.cnxids[widget].has_key(signal): if signal in self.cnxids[widget]:
err('%s already has a handler for %s' % (id(widget), signal)) err('%s already has a handler for %s' % (id(widget), signal))
self.cnxids[widget][signal] = widget.connect(signal, handler, *args) self.cnxids[widget][signal] = widget.connect(signal, handler, *args)
@ -34,31 +33,31 @@ class Signalman(object):
def remove_signal(self, widget, signal): def remove_signal(self, widget, signal):
"""Remove a signal handler""" """Remove a signal handler"""
if not self.cnxids.has_key(widget): if widget not in self.cnxids:
dbg('%s is not registered' % widget) dbg('%s is not registered' % widget)
return return
if not self.cnxids[widget].has_key(signal): if signal not in self.cnxids[widget]:
dbg('%s not registered for %s' % (signal, type(widget))) dbg('%s not registered for %s' % (signal, type(widget)))
return return
dbg('removing %s::%s' % (type(widget), signal)) dbg('removing %s::%s' % (type(widget), signal))
widget.disconnect(self.cnxids[widget][signal]) widget.disconnect(self.cnxids[widget][signal])
del(self.cnxids[widget][signal]) del(self.cnxids[widget][signal])
if len(self.cnxids[widget].keys()) == 0: if len(list(self.cnxids[widget].keys())) == 0:
dbg('no more signals for widget') dbg('no more signals for widget')
del(self.cnxids[widget]) del(self.cnxids[widget])
def remove_widget(self, widget): def remove_widget(self, widget):
"""Remove all signal handlers for a widget""" """Remove all signal handlers for a widget"""
if not self.cnxids.has_key(widget): if widget not in self.cnxids:
dbg('%s not registered' % widget) dbg('%s not registered' % widget)
return return
signals = self.cnxids[widget].keys() signals = list(self.cnxids[widget].keys())
for signal in signals: for signal in signals:
self.remove_signal(widget, signal) self.remove_signal(widget, signal)
def remove_all(self): def remove_all(self):
"""Remove all signal handlers for all widgets""" """Remove all signal handlers for all widgets"""
widgets = self.cnxids.keys() widgets = list(self.cnxids.keys())
for widget in widgets: for widget in widgets:
self.remove_widget(widget) self.remove_widget(widget)

109
terminatorlib/terminal.py Executable file → Normal file
View File

@ -1,9 +1,8 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""terminal.py - classes necessary to provide Terminal widgets""" """terminal.py - classes necessary to provide Terminal widgets"""
from __future__ import division
import os import os
import signal import signal
import gi import gi
@ -11,22 +10,27 @@ from gi.repository import GLib, GObject, Pango, Gtk, Gdk
gi.require_version('Vte', '2.91') # vte-0.38 (gnome-3.14) gi.require_version('Vte', '2.91') # vte-0.38 (gnome-3.14)
from gi.repository import Vte from gi.repository import Vte
import subprocess import subprocess
import urllib import urllib.request, urllib.parse, urllib.error
from util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup, display_manager from .util import dbg, err, spawn_new_terminator, make_uuid, manual_lookup, display_manager
import util from . import util
from config import Config from .config import Config
from cwd import get_default_cwd from .cwd import get_default_cwd
from factory import Factory from .factory import Factory
from terminator import Terminator from .terminator import Terminator
from titlebar import Titlebar from .titlebar import Titlebar
from terminal_popup_menu import TerminalPopupMenu from .terminal_popup_menu import TerminalPopupMenu
from searchbar import Searchbar from .searchbar import Searchbar
from translation import _ from .translation import _
from signalman import Signalman from .signalman import Signalman
import plugin from . import plugin
from terminatorlib.layoutlauncher import LayoutLauncher from terminatorlib.layoutlauncher import LayoutLauncher
# constant for vte matching
# TODO: Please replace with a proper reference to VTE, I found none!
PCRE2_MULTILINE = 0x00000400
# pylint: disable-msg=R0904 # pylint: disable-msg=R0904
class Terminal(Gtk.VBox): class Terminal(Gtk.VBox):
"""Class implementing the VTE widget and its wrappings""" """Class implementing the VTE widget and its wrappings"""
@ -143,8 +147,7 @@ class Terminal(Gtk.VBox):
self.vte.show() self.vte.show()
self.default_encoding = self.vte.get_encoding() self.default_encoding = self.vte.get_encoding()
self.regex_flags = (GLib.RegexCompileFlags.OPTIMIZE | \ self.regex_flags = (Vte.REGEX_FLAGS_DEFAULT | PCRE2_MULTILINE)
GLib.RegexCompileFlags.MULTILINE)
self.update_url_matches() self.update_url_matches()
self.terminalbox = self.create_terminalbox() self.terminalbox = self.create_terminalbox()
@ -232,7 +235,7 @@ class Terminal(Gtk.VBox):
try: try:
dbg('close: killing %d' % self.pid) dbg('close: killing %d' % self.pid)
os.kill(self.pid, signal.SIGHUP) os.kill(self.pid, signal.SIGHUP)
except Exception, ex: except Exception as ex:
# We really don't want to care if this failed. Deep OS voodoo is # We really don't want to care if this failed. Deep OS voodoo is
# not what we should be doing. # not what we should be doing.
dbg('os.kill failed: %s' % ex) dbg('os.kill failed: %s' % ex)
@ -255,6 +258,11 @@ class Terminal(Gtk.VBox):
return(terminalbox) return(terminalbox)
def _add_regex(self, name, re):
reg = Vte.Regex.new_for_match(re, len(re), self.regex_flags)
self.matches[name] = self.vte.match_add_regex(reg, 0)
self.vte.match_set_cursor_name(self.matches[name], 'pointer')
def update_url_matches(self): def update_url_matches(self):
"""Update the regexps used to match URLs""" """Update the regexps used to match URLs"""
userchars = "-A-Za-z0-9" userchars = "-A-Za-z0-9"
@ -271,8 +279,7 @@ class Terminal(Gtk.VBox):
re = (lboundry + schemes + re = (lboundry + schemes +
"//(" + user + "@)?[" + hostchars +".]+(:[0-9]+)?(" + "//(" + user + "@)?[" + hostchars +".]+(:[0-9]+)?(" +
urlpath + ")?" + rboundry + "/?") urlpath + ")?" + rboundry + "/?")
reg = GLib.Regex.new(re, self.regex_flags, 0) self._add_regex('full_uri', re)
self.matches['full_uri'] = self.vte.match_add_gregex(reg, 0)
if self.matches['full_uri'] == -1: if self.matches['full_uri'] == -1:
err ('Terminal::update_url_matches: Failed adding URL matches') err ('Terminal::update_url_matches: Failed adding URL matches')
@ -281,24 +288,23 @@ class Terminal(Gtk.VBox):
'(callto:|h323:|sip:)' + "[" + userchars + "+][" + '(callto:|h323:|sip:)' + "[" + userchars + "+][" +
userchars + ".]*(:[0-9]+)?@?[" + pathchars + "]+" + userchars + ".]*(:[0-9]+)?@?[" + pathchars + "]+" +
rboundry) rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0) self._add_regex('voip', re)
self.matches['voip'] = self.vte.match_add_gregex(reg, 0)
re = (lboundry + re = (lboundry +
"(www|ftp)[" + hostchars + "]*\.[" + hostchars + "(www|ftp)[" + hostchars + "]*\.[" + hostchars +
".]+(:[0-9]+)?(" + urlpath + ")?" + rboundry + "/?") ".]+(:[0-9]+)?(" + urlpath + ")?" + rboundry + "/?")
reg = GLib.Regex.new(re, self.regex_flags, 0) self._add_regex('addr_only', re)
self.matches['addr_only'] = self.vte.match_add_gregex(reg, 0)
re = (lboundry + re = (lboundry +
"(mailto:)?[a-zA-Z0-9][a-zA-Z0-9.+-]*@[a-zA-Z0-9]" + "(mailto:)?[a-zA-Z0-9][a-zA-Z0-9.+-]*@[a-zA-Z0-9]" +
"[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" + "[a-zA-Z0-9-]*\.[a-zA-Z0-9][a-zA-Z0-9-]+" +
"[.a-zA-Z0-9-]*" + rboundry) "[.a-zA-Z0-9-]*" + rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0) self._add_regex('email', re)
self.matches['email'] = self.vte.match_add_gregex(reg, 0)
re = (lboundry + re = (lboundry +
"""news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" + """news:[-A-Z\^_a-z{|}~!"#$%&'()*+,./0-9;:=?`]+@""" +
"[-A-Za-z0-9.]+(:[0-9]+)?" + rboundry) "[-A-Za-z0-9.]+(:[0-9]+)?" + rboundry)
reg = GLib.Regex.new(re, self.regex_flags, 0) self._add_regex('nntp', re)
self.matches['nntp'] = self.vte.match_add_gregex(reg, 0)
# Now add any matches from plugins # Now add any matches from plugins
try: try:
@ -312,12 +318,13 @@ class Terminal(Gtk.VBox):
if name in self.matches: if name in self.matches:
dbg('refusing to add duplicate match %s' % name) dbg('refusing to add duplicate match %s' % name)
continue continue
reg = GLib.Regex.new(match, self.regex_flags, 0)
self.matches[name] = self.vte.match_add_gregex(reg, 0) self._add_regex(name, match)
dbg('added plugin URL handler for %s (%s) as %d' % dbg('added plugin URL handler for %s (%s) as %d' %
(name, urlplugin.__class__.__name__, (name, urlplugin.__class__.__name__,
self.matches[name])) self.matches[name]))
except Exception, ex: except Exception as ex:
err('Exception occurred adding plugin URL match: %s' % ex) err('Exception occurred adding plugin URL match: %s' % ex)
def match_add(self, name, match): def match_add(self, name, match):
@ -325,8 +332,8 @@ class Terminal(Gtk.VBox):
if name in self.matches: if name in self.matches:
err('Terminal::match_add: Refusing to create duplicate match %s' % name) err('Terminal::match_add: Refusing to create duplicate match %s' % name)
return return
reg = GLib.Regex.new(match, self.regex_flags, 0)
self.matches[name] = self.vte.match_add_gregex(reg, 0) self._add_regex(name, match)
def match_remove(self, name): def match_remove(self, name):
"""Remove a previously registered URL match""" """Remove a previously registered URL match"""
@ -495,9 +502,9 @@ class Terminal(Gtk.VBox):
groupitems = [] groupitems = []
cnxs = [] cnxs = []
for key, value in {_('Broadcast _all'):'all', for key, value in list({_('Broadcast _all'):'all',
_('Broadcast _group'):'group', _('Broadcast _group'):'group',
_('Broadcast _off'):'off'}.items(): _('Broadcast _off'):'off'}.items()):
item = Gtk.RadioMenuItem.new_with_mnemonic(groupitems, key) item = Gtk.RadioMenuItem.new_with_mnemonic(groupitems, key)
groupitems = item.get_group() groupitems = item.get_group()
dbg('Terminal::populate_group_menu: %s active: %s' % dbg('Terminal::populate_group_menu: %s active: %s' %
@ -588,7 +595,7 @@ class Terminal(Gtk.VBox):
def set_groupsend(self, _widget, value): def set_groupsend(self, _widget, value):
"""Set the groupsend mode""" """Set the groupsend mode"""
# FIXME: Can we think of a smarter way of doing this than poking? # FIXME: Can we think of a smarter way of doing this than poking?
if value in self.terminator.groupsend_type.values(): if value in list(self.terminator.groupsend_type.values()):
dbg('Terminal::set_groupsend: setting groupsend to %s' % value) dbg('Terminal::set_groupsend: setting groupsend to %s' % value)
self.terminator.groupsend = value self.terminator.groupsend = value
@ -714,15 +721,15 @@ class Terminal(Gtk.VBox):
if len(colors) == 16: if len(colors) == 16:
# RGB values for indices 16..255 copied from vte source in order to dim them # RGB values for indices 16..255 copied from vte source in order to dim them
shades = [0, 95, 135, 175, 215, 255] shades = [0, 95, 135, 175, 215, 255]
for r in xrange(0, 6): for r in range(0, 6):
for g in xrange(0, 6): for g in range(0, 6):
for b in xrange(0, 6): for b in range(0, 6):
newcolor = Gdk.RGBA() newcolor = Gdk.RGBA()
setattr(newcolor, "red", shades[r] / 255.0) setattr(newcolor, "red", shades[r] / 255.0)
setattr(newcolor, "green", shades[g] / 255.0) setattr(newcolor, "green", shades[g] / 255.0)
setattr(newcolor, "blue", shades[b] / 255.0) setattr(newcolor, "blue", shades[b] / 255.0)
self.palette_active.append(newcolor) self.palette_active.append(newcolor)
for y in xrange(8, 248, 10): for y in range(8, 248, 10):
newcolor = Gdk.RGBA() newcolor = Gdk.RGBA()
setattr(newcolor, "red", y / 255.0) setattr(newcolor, "red", y / 255.0)
setattr(newcolor, "green", y / 255.0) setattr(newcolor, "green", y / 255.0)
@ -743,7 +750,7 @@ class Terminal(Gtk.VBox):
self.palette_inactive) self.palette_inactive)
profiles = self.config.base.profiles profiles = self.config.base.profiles
terminal_box_style_context = self.terminalbox.get_style_context() terminal_box_style_context = self.terminalbox.get_style_context()
for profile in profiles.keys(): for profile in list(profiles.keys()):
munged_profile = "terminator-profile-%s" % ( munged_profile = "terminator-profile-%s" % (
"".join([c if c.isalnum() else "-" for c in profile])) "".join([c if c.isalnum() else "-" for c in profile]))
if terminal_box_style_context.has_class(munged_profile): if terminal_box_style_context.has_class(munged_profile):
@ -1016,7 +1023,7 @@ class Terminal(Gtk.VBox):
_time, data): _time, data):
"""I have no idea what this does, drag and drop is a mystery. sorry.""" """I have no idea what this does, drag and drop is a mystery. sorry."""
selection_data.set(Gdk.atom_intern('vte', False), info, selection_data.set(Gdk.atom_intern('vte', False), info,
str(data.terminator.terminals.index(self))) bytes(str(data.terminator.terminals.index(self)), 'utf-8'))
def on_drag_motion(self, widget, drag_context, x, y, _time, _data): def on_drag_motion(self, widget, drag_context, x, y, _time, _data):
"""*shrug*""" """*shrug*"""
@ -1113,7 +1120,7 @@ class Terminal(Gtk.VBox):
str='' str=''
for fname in txt_lines[:-1]: for fname in txt_lines[:-1]:
dbg('drag data fname: %s' % fname) dbg('drag data fname: %s' % fname)
fname = "'%s'" % urllib.unquote(fname[7:].replace("'", fname = "'%s'" % urllib.parse.unquote(fname[7:].replace("'",
'\'\\\'\'')) '\'\\\'\''))
str += fname + ' ' str += fname + ' '
txt=str txt=str
@ -1453,7 +1460,7 @@ class Terminal(Gtk.VBox):
url = 'ftp://' + url url = 'ftp://' + url
elif match == self.matches['addr_only']: elif match == self.matches['addr_only']:
url = 'http://' + url url = 'http://' + url
elif match in self.matches.values(): elif match in list(self.matches.values()):
# We have a match, but it's not a hard coded one, so it's a plugin # We have a match, but it's not a hard coded one, so it's a plugin
try: try:
registry = plugin.PluginRegistry() registry = plugin.PluginRegistry()
@ -1468,7 +1475,7 @@ class Terminal(Gtk.VBox):
%s plugin' % urlplugin.handler_name) %s plugin' % urlplugin.handler_name)
url = newurl url = newurl
break break
except Exception, ex: except Exception as ex:
err('Exception occurred preparing URL: %s' % ex) err('Exception occurred preparing URL: %s' % ex)
return(url) return(url)
@ -1629,20 +1636,20 @@ class Terminal(Gtk.VBox):
def create_layout(self, layout): def create_layout(self, layout):
"""Apply our layout""" """Apply our layout"""
dbg('Setting layout') dbg('Setting layout')
if layout.has_key('command') and layout['command'] != '': if 'command' in layout and layout['command'] != '':
self.layout_command = layout['command'] self.layout_command = layout['command']
if layout.has_key('profile') and layout['profile'] != '': if 'profile' in layout and layout['profile'] != '':
if layout['profile'] in self.config.list_profiles(): if layout['profile'] in self.config.list_profiles():
self.set_profile(self, layout['profile']) self.set_profile(self, layout['profile'])
if layout.has_key('group') and layout['group'] != '': if 'group' in layout and layout['group'] != '':
# This doesn't need/use self.titlebar, but it's safer than sending # This doesn't need/use self.titlebar, but it's safer than sending
# None # None
self.really_create_group(self.titlebar, layout['group']) self.really_create_group(self.titlebar, layout['group'])
if layout.has_key('title') and layout['title'] != '': if 'title' in layout and layout['title'] != '':
self.titlebar.set_custom_string(layout['title']) self.titlebar.set_custom_string(layout['title'])
if layout.has_key('directory') and layout['directory'] != '': if 'directory' in layout and layout['directory'] != '':
self.directory = layout['directory'] self.directory = layout['directory']
if layout.has_key('uuid') and layout['uuid'] != '': if 'uuid' in layout and layout['uuid'] != '':
self.uuid = make_uuid(layout['uuid']) self.uuid = make_uuid(layout['uuid'])
def scroll_by_page(self, pages): def scroll_by_page(self, pages):

29
terminatorlib/terminal_popup_menu.py Executable file → Normal file
View File

@ -1,21 +1,18 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""terminal_popup_menu.py - classes necessary to provide a terminal context """terminal_popup_menu.py - classes necessary to provide a terminal context
menu""" menu"""
import string
from gi.repository import Gtk from gi.repository import Gtk
from version import APP_NAME from .version import APP_NAME
from translation import _ from .translation import _
from encoding import TerminatorEncoding from .encoding import TerminatorEncoding
from terminator import Terminator from .terminator import Terminator
from util import err, dbg from .util import err, dbg
from config import Config from .config import Config
from prefseditor import PrefsEditor from .prefseditor import PrefsEditor
import plugin from . import plugin
class TerminalPopupMenu(object): class TerminalPopupMenu(object):
"""Class implementing the Terminal context menu""" """Class implementing the Terminal context menu"""
@ -51,7 +48,7 @@ class TerminalPopupMenu(object):
if url and url[0]: if url and url[0]:
dbg("URL matches id: %d" % url[1]) dbg("URL matches id: %d" % url[1])
if not url[1] in terminal.matches.values(): if not url[1] in list(terminal.matches.values()):
err("Unknown URL match id: %d" % url[1]) err("Unknown URL match id: %d" % url[1])
dbg("Available matches: %s" % terminal.matches) dbg("Available matches: %s" % terminal.matches)
@ -63,7 +60,7 @@ class TerminalPopupMenu(object):
elif url[1] == terminal.matches['voip']: elif url[1] == terminal.matches['voip']:
nameopen = _('Ca_ll VoIP address') nameopen = _('Ca_ll VoIP address')
namecopy = _('_Copy VoIP address') namecopy = _('_Copy VoIP address')
elif url[1] in terminal.matches.values(): elif url[1] in list(terminal.matches.values()):
# This is a plugin match # This is a plugin match
for pluginname in terminal.matches: for pluginname in terminal.matches:
if terminal.matches[pluginname] == url[1]: if terminal.matches[pluginname] == url[1]:
@ -191,7 +188,7 @@ class TerminalPopupMenu(object):
item.connect('activate', lambda x: PrefsEditor(self.terminal)) item.connect('activate', lambda x: PrefsEditor(self.terminal))
menu.append(item) menu.append(item)
profilelist = sorted(self.config.list_profiles(), key=string.lower) profilelist = sorted(self.config.list_profiles(), key=str.lower)
if len(profilelist) > 1: if len(profilelist) > 1:
item = Gtk.MenuItem.new_with_mnemonic(_('Profiles')) item = Gtk.MenuItem.new_with_mnemonic(_('Profiles'))
@ -228,7 +225,7 @@ class TerminalPopupMenu(object):
for menuitem in menuitems: for menuitem in menuitems:
menu.append(menuitem) menu.append(menuitem)
except Exception, ex: except Exception as ex:
err('TerminalPopupMenu::show: %s' % ex) err('TerminalPopupMenu::show: %s' % ex)
menu.show_all() menu.show_all()
@ -246,7 +243,7 @@ class TerminalPopupMenu(object):
submenu = Gtk.Menu () submenu = Gtk.Menu ()
item.set_submenu (submenu) item.set_submenu (submenu)
encodings = TerminatorEncoding ().get_list () encodings = TerminatorEncoding ().get_list ()
encodings.sort (lambda x, y: cmp (x[2].lower (), y[2].lower ())) encodings.sort (key=lambda x: x[2].lower ())
current_encoding = terminal.vte.get_encoding () current_encoding = terminal.vte.get_encoding ()
group = None group = None

53
terminatorlib/terminator.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""terminator.py - class for the master Terminator singleton""" """terminator.py - class for the master Terminator singleton"""
@ -10,14 +9,14 @@ gi.require_version('Vte', '2.91')
from gi.repository import Gtk, Gdk, Vte, GdkX11 from gi.repository import Gtk, Gdk, Vte, GdkX11
from gi.repository.GLib import GError from gi.repository.GLib import GError
import borg from . import borg
from borg import Borg from .borg import Borg
from config import Config from .config import Config
from keybindings import Keybindings from .keybindings import Keybindings
from util import dbg, err, enumerate_descendants from .util import dbg, err, enumerate_descendants
from factory import Factory from .factory import Factory
from cwd import get_pid_cwd from .cwd import get_pid_cwd
from version import APP_NAME, APP_VERSION from .version import APP_NAME, APP_VERSION
def eventkey2gdkevent(eventkey): # FIXME FOR GTK3: is there a simpler way of casting from specific EventKey to generic (union) GdkEvent? def eventkey2gdkevent(eventkey): # FIXME FOR GTK3: is there a simpler way of casting from specific EventKey to generic (union) GdkEvent?
gdkevent = Gdk.Event.new(eventkey.type) gdkevent = Gdk.Event.new(eventkey.type)
@ -267,34 +266,34 @@ class Terminator(Borg):
count = count + 1 count = count + 1
if count == 1000: if count == 1000:
err('hit maximum loop boundary. THIS IS VERY LIKELY A BUG') err('hit maximum loop boundary. THIS IS VERY LIKELY A BUG')
for obj in layout.keys(): for obj in list(layout.keys()):
if layout[obj]['type'].lower() == 'window': if layout[obj]['type'].lower() == 'window':
hierarchy[obj] = {} hierarchy[obj] = {}
hierarchy[obj]['type'] = 'Window' hierarchy[obj]['type'] = 'Window'
hierarchy[obj]['children'] = {} hierarchy[obj]['children'] = {}
# Copy any additional keys # Copy any additional keys
for objkey in layout[obj].keys(): for objkey in list(layout[obj].keys()):
if layout[obj][objkey] != '' and not hierarchy[obj].has_key(objkey): if layout[obj][objkey] != '' and objkey not in hierarchy[obj]:
hierarchy[obj][objkey] = layout[obj][objkey] hierarchy[obj][objkey] = layout[obj][objkey]
objects[obj] = hierarchy[obj] objects[obj] = hierarchy[obj]
del(layout[obj]) del(layout[obj])
else: else:
# Now examine children to see if their parents exist yet # Now examine children to see if their parents exist yet
if not layout[obj].has_key('parent'): if 'parent' not in layout[obj]:
err('Invalid object: %s' % obj) err('Invalid object: %s' % obj)
del(layout[obj]) del(layout[obj])
continue continue
if objects.has_key(layout[obj]['parent']): if layout[obj]['parent'] in objects:
# Our parent has been created, add ourselves # Our parent has been created, add ourselves
childobj = {} childobj = {}
childobj['type'] = layout[obj]['type'] childobj['type'] = layout[obj]['type']
childobj['children'] = {} childobj['children'] = {}
# Copy over any additional object keys # Copy over any additional object keys
for objkey in layout[obj].keys(): for objkey in list(layout[obj].keys()):
if not childobj.has_key(objkey): if objkey not in childobj:
childobj[objkey] = layout[obj][objkey] childobj[objkey] = layout[obj][objkey]
objects[layout[obj]['parent']]['children'][obj] = childobj objects[layout[obj]['parent']]['children'][obj] = childobj
@ -309,25 +308,25 @@ class Terminator(Borg):
raise(ValueError) raise(ValueError)
dbg('Creating a window') dbg('Creating a window')
window, terminal = self.new_window() window, terminal = self.new_window()
if layout[windef].has_key('position'): if 'position' in layout[windef]:
parts = layout[windef]['position'].split(':') parts = layout[windef]['position'].split(':')
if len(parts) == 2: if len(parts) == 2:
window.move(int(parts[0]), int(parts[1])) window.move(int(parts[0]), int(parts[1]))
if layout[windef].has_key('size'): if 'size' in layout[windef]:
parts = layout[windef]['size'] parts = layout[windef]['size']
winx = int(parts[0]) winx = int(parts[0])
winy = int(parts[1]) winy = int(parts[1])
if winx > 1 and winy > 1: if winx > 1 and winy > 1:
window.resize(winx, winy) window.resize(winx, winy)
if layout[windef].has_key('title'): if 'title' in layout[windef]:
window.title.force_title(layout[windef]['title']) window.title.force_title(layout[windef]['title'])
if layout[windef].has_key('maximised'): if 'maximised' in layout[windef]:
if layout[windef]['maximised'] == 'True': if layout[windef]['maximised'] == 'True':
window.ismaximised = True window.ismaximised = True
else: else:
window.ismaximised = False window.ismaximised = False
window.set_maximised(window.ismaximised) window.set_maximised(window.ismaximised)
if layout[windef].has_key('fullscreen'): if 'fullscreen' in layout[windef]:
if layout[windef]['fullscreen'] == 'True': if layout[windef]['fullscreen'] == 'True':
window.isfullscreen = True window.isfullscreen = True
else: else:
@ -359,7 +358,7 @@ class Terminator(Borg):
# For windows with a notebook # For windows with a notebook
notebook = window.get_toplevel().get_children()[0] notebook = window.get_toplevel().get_children()[0]
# Cycle through pages by number # Cycle through pages by number
for page in xrange(0, notebook.get_n_pages()): for page in range(0, notebook.get_n_pages()):
# Try and get the entry in the previously saved mapping # Try and get the entry in the previously saved mapping
mapping = window_last_active_term_mapping[window] mapping = window_last_active_term_mapping[window]
page_last_active_term = mapping.get(notebook.get_nth_page(page), None) page_last_active_term = mapping.get(notebook.get_nth_page(page), None)
@ -475,7 +474,7 @@ class Terminator(Borg):
background-color: alpha(%s, %s); } background-color: alpha(%s, %s); }
""" """
profiles = self.config.base.profiles profiles = self.config.base.profiles
for profile in profiles.keys(): for profile in list(profiles.keys()):
if profiles[profile]['use_theme_colors']: if profiles[profile]['use_theme_colors']:
# Create a dummy window/vte and realise it so it has correct # Create a dummy window/vte and realise it so it has correct
# values to read from # values to read from
@ -502,7 +501,7 @@ class Terminator(Borg):
css += template % (munged_profile, bgcolor, bgalpha) css += template % (munged_profile, bgcolor, bgalpha)
style_provider = Gtk.CssProvider() style_provider = Gtk.CssProvider()
style_provider.load_from_data(css) style_provider.load_from_data(css.encode('utf-8'))
self.style_providers.append(style_provider) self.style_providers.append(style_provider)
# Attempt to load some theme specific stylistic tweaks for appearances # Attempt to load some theme specific stylistic tweaks for appearances
@ -538,19 +537,19 @@ class Terminator(Borg):
# Size the GtkPaned splitter handle size. # Size the GtkPaned splitter handle size.
css = "" css = ""
if self.config['handle_size'] in xrange(0, 21): if self.config['handle_size'] in range(0, 21):
css += """ css += """
.terminator-terminal-window GtkPaned, .terminator-terminal-window GtkPaned,
.terminator-terminal-window paned { .terminator-terminal-window paned {
-GtkPaned-handle-size: %s; } -GtkPaned-handle-size: %s; }
""" % self.config['handle_size'] """ % self.config['handle_size']
style_provider = Gtk.CssProvider() style_provider = Gtk.CssProvider()
style_provider.load_from_data(css) style_provider.load_from_data(css.encode('utf-8'))
self.style_providers.append(style_provider) self.style_providers.append(style_provider)
# Apply the providers, incrementing priority so they don't cancel out # Apply the providers, incrementing priority so they don't cancel out
# each other # each other
for idx in xrange(0, len(self.style_providers)): for idx in range(0, len(self.style_providers)):
Gtk.StyleContext.add_provider_for_screen( Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(), Gdk.Screen.get_default(),
self.style_providers[idx], self.style_providers[idx],

11
terminatorlib/titlebar.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""titlebar.py - classes necessary to provide a terminal title bar""" """titlebar.py - classes necessary to provide a terminal title bar"""
@ -9,11 +8,11 @@ from gi.repository import Pango
import random import random
import itertools import itertools
from version import APP_NAME from .version import APP_NAME
from util import dbg from .util import dbg
from terminator import Terminator from .terminator import Terminator
from editablelabel import EditableLabel from .editablelabel import EditableLabel
from translation import _ from .translation import _
# pylint: disable-msg=R0904 # pylint: disable-msg=R0904
# pylint: disable-msg=W0613 # pylint: disable-msg=W0613

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator - multiple gnome terminals in one window # Terminator - multiple gnome terminals in one window
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -17,8 +16,8 @@
"""Terminator by Chris Jones <cmsj@tenshu.net>""" """Terminator by Chris Jones <cmsj@tenshu.net>"""
from version import APP_NAME from .version import APP_NAME
from util import dbg from .util import dbg
_ = None _ = None

7
terminatorlib/util.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator.util - misc utility functions # Terminator.util - misc utility functions
# Copyright (C) 2006-2010 cmsj@tenshu.net # Copyright (C) 2006-2010 cmsj@tenshu.net
# #
@ -64,14 +63,14 @@ def dbg(log = ""):
if DEBUGMETHODS != [] and method not in DEBUGMETHODS: if DEBUGMETHODS != [] and method not in DEBUGMETHODS:
return return
try: try:
print >> sys.stderr, "%s::%s: %s%s" % (classname, method, log, extra) print("%s::%s: %s%s" % (classname, method, log, extra), file=sys.stderr)
except IOError: except IOError:
pass pass
def err(log = ""): def err(log = ""):
"""Print an error message""" """Print an error message"""
try: try:
print >> sys.stderr, log print(log, file=sys.stderr)
except IOError: except IOError:
pass pass
@ -279,7 +278,7 @@ def enumerate_descendants(parent):
terminals""" terminals"""
# FIXME: Does having to import this here mean we should move this function # FIXME: Does having to import this here mean we should move this function
# back to Container? # back to Container?
from factory import Factory from .factory import Factory
containerstmp = [] containerstmp = []
containers = [] containers = []

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# TerminatorVersion - version number # TerminatorVersion - version number
# Copyright (C) 2010 cmsj@tenshu.net # Copyright (C) 2010 cmsj@tenshu.net
# #

27
terminatorlib/window.py Executable file → Normal file
View File

@ -1,4 +1,3 @@
#!/usr/bin/env python2
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""window.py - class for the main Terminator window""" """window.py - class for the main Terminator window"""
@ -10,13 +9,13 @@ import gi
from gi.repository import GObject from gi.repository import GObject
from gi.repository import Gtk, Gdk, GdkX11 from gi.repository import Gtk, Gdk, GdkX11
from util import dbg, err, make_uuid, display_manager from .util import dbg, err, make_uuid, display_manager
import util from . import util
from translation import _ from .translation import _
from version import APP_NAME from .version import APP_NAME
from container import Container from .container import Container
from factory import Factory from .factory import Factory
from terminator import Terminator from .terminator import Terminator
if display_manager() == 'X11': if display_manager() == 'X11':
try: try:
@ -837,9 +836,9 @@ class Window(Container, Gtk.Window):
for term in possibles: for term in possibles:
rect = layout[term] rect = layout[term]
offsets[term] = util.get_nav_offset(edge, rect, direction) offsets[term] = util.get_nav_offset(edge, rect, direction)
keys = offsets.values() keys = list(offsets.values())
keys.sort() keys.sort()
winners = [k for k, v in offsets.iteritems() if v == keys[0]] winners = [k for k, v in offsets.items() if v == keys[0]]
next = terminals.index(winners[0]) next = terminals.index(winners[0])
if len(winners) > 1: if len(winners) > 1:
@ -862,7 +861,7 @@ class Window(Container, Gtk.Window):
def create_layout(self, layout): def create_layout(self, layout):
"""Apply any config items from our layout""" """Apply any config items from our layout"""
if not layout.has_key('children'): if 'children' not in layout:
err('layout describes no children: %s' % layout) err('layout describes no children: %s' % layout)
return return
children = layout['children'] children = layout['children']
@ -871,7 +870,7 @@ class Window(Container, Gtk.Window):
err('incorrect number of children for Window: %s' % layout) err('incorrect number of children for Window: %s' % layout)
return return
child = children[children.keys()[0]] child = children[list(children.keys())[0]]
terminal = self.get_children()[0] terminal = self.get_children()[0]
dbg('Making a child of type: %s' % child['type']) dbg('Making a child of type: %s' % child['type'])
if child['type'] == 'VPaned': if child['type'] == 'VPaned':
@ -892,10 +891,10 @@ class Window(Container, Gtk.Window):
self.get_children()[0].create_layout(child) self.get_children()[0].create_layout(child)
if layout.has_key('last_active_term') and layout['last_active_term'] not in ['', None]: if 'last_active_term' in layout and layout['last_active_term'] not in ['', None]:
self.last_active_term = make_uuid(layout['last_active_term']) self.last_active_term = make_uuid(layout['last_active_term'])
if layout.has_key('last_active_window') and layout['last_active_window'] == 'True': if 'last_active_window' in layout and layout['last_active_window'] == 'True':
self.terminator.last_active_window = self.uuid self.terminator.last_active_window = self.uuid
class WindowTitle(object): class WindowTitle(object):

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
"""Load up the tests.""" """Load up the tests."""
import os import os

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""testborg.py - We are the borg. Resistance is futile. """testborg.py - We are the borg. Resistance is futile.
@ -57,3 +57,4 @@ class TestBorg2(Borg):
if not self.attribute: if not self.attribute:
self.attribute = 1 self.attribute = 1
# TODO: implement test?

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
# Terminator by Chris Jones <cmsj@tenshu.net> # Terminator by Chris Jones <cmsj@tenshu.net>
# GPL v2 only # GPL v2 only
"""testsignalman.py - Test the signalman class """testsignalman.py - Test the signalman class
@ -53,11 +53,11 @@ class TestWidget():
del(self.signals[signalid]) del(self.signals[signalid])
def handler(): def handler():
print "I am a test handler" print("I am a test handler")
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
import doctest import doctest
(failed, attempted) = doctest.testmod() (failed, attempted) = doctest.testmod()
print "%d/%d tests failed" % (failed, attempted) print("%d/%d tests failed" % (failed, attempted))
sys.exit(failed) sys.exit(failed)