Merged with main branch [with chantra's tab]
This commit is contained in:
parent
3086c75429
commit
13b8778d0b
15
ChangeLog
15
ChangeLog
|
@ -3,8 +3,19 @@ terminator 0.9:
|
||||||
* Added kwybindings for terms size and scrollbar manipulation. Thanks
|
* Added kwybindings for terms size and scrollbar manipulation. Thanks
|
||||||
Emmanuel Bretelle.
|
Emmanuel Bretelle.
|
||||||
* Completely revamped config system which now transparently makes use
|
* Completely revamped config system which now transparently makes use
|
||||||
of gconf settings if they are available, falls back to sensible
|
of gconf settings if they are available, falls back to sensible
|
||||||
defaults if not, and can be overridden entirely by ~/.terminatorrc
|
defaults if not, and can be overridden entirely by ~/.terminatorrc
|
||||||
|
* New application icon from Cory Kontros
|
||||||
|
* FreeBSD support (thanks to Thomas Hurst)
|
||||||
|
* Watch the system monospace font setting. Closes LP #197960
|
||||||
|
* Proxy support (via GNOME and $http_proxy)
|
||||||
|
* GConf backend now caches
|
||||||
|
* Fix redundant title when there is only one Term. Closes LP#215210
|
||||||
|
* Try much harder to find a usable shell
|
||||||
|
* Support encodings a-la GNOME Terminal
|
||||||
|
* Move python support code to a terminatorlib module
|
||||||
|
* Tab support
|
||||||
|
* Drag & Drop support
|
||||||
|
|
||||||
terminator 0.8.1:
|
terminator 0.8.1:
|
||||||
* Fixed ChangeLog
|
* Fixed ChangeLog
|
||||||
|
|
1
TODO
1
TODO
|
@ -1,2 +1 @@
|
||||||
* Edit doc/terminatorrc.5 manpage to contain the information about the options
|
* Edit doc/terminatorrc.5 manpage to contain the information about the options
|
||||||
* Write a Tab feature for terminator
|
|
||||||
|
|
|
@ -9,9 +9,13 @@ Upstream Authors:
|
||||||
Huang He
|
Huang He
|
||||||
Kees Cook
|
Kees Cook
|
||||||
Thomas Meire
|
Thomas Meire
|
||||||
|
Nicolas Valcarcel
|
||||||
|
Emmanuel Bretelle
|
||||||
|
Chris Oattes
|
||||||
|
|
||||||
Artwork:
|
Artwork:
|
||||||
Cristian Grada - Drew our icon and licenced it to us under this licence
|
Cory Kontros - Produced our current icon under the CC-by-SA licence
|
||||||
|
Cristian Grada - Drew our original icon and licenced it to us under this licence
|
||||||
|
|
||||||
Translations:
|
Translations:
|
||||||
Thomas Meire
|
Thomas Meire
|
||||||
|
|
|
@ -85,7 +85,7 @@ Toggle fullscreen
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR gnome\-terminal(1),terminatorrc(5)
|
.BR gnome\-terminal(1),terminatorrc(5)
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
Terminator was written by Chris Jones <cmsj@tenshu.net>
|
Terminator was written by Chris Jones <cmsj@tenshu.net> and others.
|
||||||
.PP
|
.PP
|
||||||
This manual page was written by Chris Jones <cmsj@tenshu.net>
|
This manual page was written by Chris Jones <cmsj@tenshu.net>
|
||||||
for the Ubuntu project (but may be used by others).
|
for the Ubuntu project (but may be used by others).
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -84,7 +84,7 @@ setup(name='Terminator',
|
||||||
('share/icons/hicolor/24x24/apps', glob.glob('data/icons/24x24/apps/*.png')),
|
('share/icons/hicolor/24x24/apps', glob.glob('data/icons/24x24/apps/*.png')),
|
||||||
('share/icons/hicolor/48x48/apps', glob.glob('data/icons/48x48/apps/*.png')),
|
('share/icons/hicolor/48x48/apps', glob.glob('data/icons/48x48/apps/*.png')),
|
||||||
],
|
],
|
||||||
py_modules=['terminatorconfig'],
|
packages=['terminatorlib'],
|
||||||
cmdclass={'build': BuildData, 'install_data': InstallData}
|
cmdclass={'build': BuildData, 'install_data': InstallData}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
532
terminator
532
terminator
|
@ -35,8 +35,25 @@ except:
|
||||||
# import unix-lib
|
# import unix-lib
|
||||||
import pwd
|
import pwd
|
||||||
|
|
||||||
|
TARGET_TYPE_VTE = 8
|
||||||
|
|
||||||
# import our configuration loader
|
# import our configuration loader
|
||||||
import terminatorconfig
|
from terminatorlib import config
|
||||||
|
from terminatorlib.config import dbg
|
||||||
|
|
||||||
|
#import encoding list
|
||||||
|
from terminatorlib.encoding import TerminatorEncoding
|
||||||
|
|
||||||
|
# Sort out cwd detection code, if available
|
||||||
|
pid_get_cwd = lambda pid: None
|
||||||
|
if platform.system() == 'FreeBSD':
|
||||||
|
try:
|
||||||
|
from terminatorlib import freebsd
|
||||||
|
pid_get_cwd = lambda pid: freebsd.get_process_cwd(pid)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif platform.system == 'Linux':
|
||||||
|
pid_get_cwd = lambda pid: os.path.realpath ('/proc/%s/cwd' % pid)
|
||||||
|
|
||||||
# import gtk libs
|
# import gtk libs
|
||||||
# check just in case anyone runs it on a non-gnome system.
|
# check just in case anyone runs it on a non-gnome system.
|
||||||
|
@ -125,6 +142,22 @@ class TerminatorTerm (gtk.VBox):
|
||||||
self._vte.connect ("key-press-event", self.on_vte_key_press)
|
self._vte.connect ("key-press-event", self.on_vte_key_press)
|
||||||
self._vte.connect ("button-press-event", self.on_vte_button_press)
|
self._vte.connect ("button-press-event", self.on_vte_button_press)
|
||||||
self._vte.connect ("popup-menu", self.on_vte_popup_menu)
|
self._vte.connect ("popup-menu", self.on_vte_popup_menu)
|
||||||
|
|
||||||
|
"""drag and drop"""
|
||||||
|
srcvtetargets = [ ( "vte", gtk.TARGET_SAME_APP, TARGET_TYPE_VTE ) ]
|
||||||
|
dsttargets = [ ( "vte", gtk.TARGET_SAME_APP, TARGET_TYPE_VTE ), ('text/plain', 0, 0) , ("STRING", 0, 0), ("COMPOUND_TEXT", 0, 0)]
|
||||||
|
self._vte.drag_source_set( gtk.gdk.CONTROL_MASK | gtk.gdk.BUTTON3_MASK, srcvtetargets, gtk.gdk.ACTION_MOVE)
|
||||||
|
self._titlebox.drag_source_set( gtk.gdk.BUTTON1_MASK, srcvtetargets, gtk.gdk.ACTION_MOVE)
|
||||||
|
#self._vte.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT |gtk.DEST_DEFAULT_DROP ,dsttargets, gtk.gdk.ACTION_MOVE)
|
||||||
|
self._vte.drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT |gtk.DEST_DEFAULT_DROP ,dsttargets, gtk.gdk.ACTION_MOVE)
|
||||||
|
self._vte.connect("drag-begin", self.on_drag_begin, self)
|
||||||
|
self._titlebox.connect("drag-begin", self.on_drag_begin, self)
|
||||||
|
self._vte.connect("drag-data-get", self.on_drag_data_get, self)
|
||||||
|
self._titlebox.connect("drag-data-get", self.on_drag_data_get, self)
|
||||||
|
#for testing purpose: drag-motion
|
||||||
|
self._vte.connect("drag-motion", self.on_drag_motion, self)
|
||||||
|
self._vte.connect("drag-data-received", self.on_drag_data_received, self)
|
||||||
|
|
||||||
self._vte.connect ("composited-changed", self.on_composited_changed)
|
self._vte.connect ("composited-changed", self.on_composited_changed)
|
||||||
self._vte.connect ("window-title-changed", self.on_vte_title_change)
|
self._vte.connect ("window-title-changed", self.on_vte_title_change)
|
||||||
self._vte.connect ("grab-focus", self.on_vte_focus)
|
self._vte.connect ("grab-focus", self.on_vte_focus)
|
||||||
|
@ -150,6 +183,146 @@ class TerminatorTerm (gtk.VBox):
|
||||||
|
|
||||||
os.putenv ('COLORTERM', 'gnome-terminal')
|
os.putenv ('COLORTERM', 'gnome-terminal')
|
||||||
|
|
||||||
|
def on_drag_begin(self, widget, drag_context, data):
|
||||||
|
dbg ('Drag begins')
|
||||||
|
if os.path.exists("/usr/share/icons/hicolor/48x48/apps/terminator.png"):
|
||||||
|
widget.drag_source_set_icon_pixbuf( gtk.gdk.pixbuf_new_from_file("/usr/share/icons/hicolor/48x48/apps/terminator.png"))
|
||||||
|
|
||||||
|
def on_drag_data_get(self,widget, drag_context, selection_data, info, time, data):
|
||||||
|
dbg ("Drag data get")
|
||||||
|
selection_data.set("vte",info, str(data.terminator.term_list.index (self)))
|
||||||
|
|
||||||
|
|
||||||
|
def on_drag_motion(self, widget, drag_context, x, y, time, data):
|
||||||
|
dbg ("Drag Motion on ")
|
||||||
|
"""
|
||||||
|
x-special/gnome-icon-list
|
||||||
|
text/uri-list
|
||||||
|
UTF8_STRING
|
||||||
|
COMPOUND_TEXT
|
||||||
|
TEXT
|
||||||
|
STRING
|
||||||
|
text/plain;charset=utf-8
|
||||||
|
text/plain;charset=UTF-8
|
||||||
|
text/plain
|
||||||
|
"""
|
||||||
|
|
||||||
|
if 'text/plain' in drag_context.targets:
|
||||||
|
#copy text from another widget
|
||||||
|
return
|
||||||
|
srcwidget = drag_context.get_source_widget()
|
||||||
|
if (isinstance(srcwidget, gtk.EventBox) and srcwidget == self._titlebox) or widget == srcwidget:
|
||||||
|
#on self
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
alloc = widget.allocation
|
||||||
|
rect = gtk.gdk.Rectangle(0, 0, alloc.width, alloc.height)
|
||||||
|
widget.window.invalidate_rect(rect, True)
|
||||||
|
widget.window.process_updates(True)
|
||||||
|
|
||||||
|
context = widget.window.cairo_create()
|
||||||
|
if self.conf.use_theme_colors:
|
||||||
|
color = self._vte.get_style ().text[gtk.STATE_NORMAL]
|
||||||
|
else:
|
||||||
|
color = gtk.gdk.color_parse (self.conf.foreground_color)
|
||||||
|
|
||||||
|
|
||||||
|
context.set_source_rgba(color.red, color.green, color.blue, 0.5)
|
||||||
|
|
||||||
|
pos = self.get_location(widget, x, y)
|
||||||
|
topleft = (0,0)
|
||||||
|
topright = (alloc.width,0)
|
||||||
|
topmiddle = (alloc.width/2,0)
|
||||||
|
bottomleft = (0, alloc.height)
|
||||||
|
bottomright = (alloc.width,alloc.height)
|
||||||
|
bottommiddle = (alloc.width/2, alloc.height)
|
||||||
|
middle = (alloc.width/2, alloc.height/2)
|
||||||
|
middleleft = (0, alloc.height/2)
|
||||||
|
middleright = (alloc.width, alloc.height/2)
|
||||||
|
#print "%f %f %d %d" %(coef1, coef2, b1,b2)
|
||||||
|
coord = ()
|
||||||
|
if pos == "right":
|
||||||
|
coord = (topright, topmiddle, bottommiddle, bottomright)
|
||||||
|
if pos == "top":
|
||||||
|
coord = (topleft, topright, middleright , middleleft)
|
||||||
|
if pos == "left":
|
||||||
|
coord = (topleft, topmiddle, bottommiddle, bottomleft)
|
||||||
|
if pos == "bottom":
|
||||||
|
coord = (bottomleft, bottomright, middleright , middleleft)
|
||||||
|
|
||||||
|
if len(coord) > 0 :
|
||||||
|
context.move_to(coord[len(coord)-1][0],coord[len(coord)-1][1])
|
||||||
|
for i in coord:
|
||||||
|
context.line_to(i[0],i[1])
|
||||||
|
|
||||||
|
context.fill()
|
||||||
|
|
||||||
|
|
||||||
|
def on_drag_drop(self, widget, drag_context, x, y, time):
|
||||||
|
parent = widget.get_parent()
|
||||||
|
dbg ('Drag drop on %s'%parent)
|
||||||
|
|
||||||
|
def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time, data):
|
||||||
|
dbg ("Drag Data Received")
|
||||||
|
if selection_data.type == 'text/plain':
|
||||||
|
#copy text to destination
|
||||||
|
#print "%s %s" % (selection_data.type, selection_data.target)
|
||||||
|
txt = selection_data.data.strip()
|
||||||
|
if txt[0:7] == "file://":
|
||||||
|
txt = "'%s'" % txt[7:]
|
||||||
|
self._vte.feed_child(txt)
|
||||||
|
return
|
||||||
|
|
||||||
|
widgetsrc = data.terminator.term_list[int(selection_data.data)]
|
||||||
|
srcvte = drag_context.get_source_widget()
|
||||||
|
#check if computation requireds
|
||||||
|
if (isinstance(srcvte, gtk.EventBox) and srcvte == self._titlebox) or srcvte == widget:
|
||||||
|
dbg (" on itself")
|
||||||
|
return
|
||||||
|
|
||||||
|
srchbox = widgetsrc
|
||||||
|
dsthbox = widget.get_parent().get_parent()
|
||||||
|
|
||||||
|
dstpaned = dsthbox.get_parent()
|
||||||
|
srcpaned = srchbox.get_parent()
|
||||||
|
if isinstance(dstpaned, gtk.Window) and isinstance(srcpaned, gtk.Window):
|
||||||
|
dbg (" Only one terminal")
|
||||||
|
return
|
||||||
|
pos = self.get_location(widget, x, y)
|
||||||
|
|
||||||
|
data.terminator.remove(widgetsrc)
|
||||||
|
data.terminator.add(self, widgetsrc,pos)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_location(self, vte, x, y):
|
||||||
|
pos = ""
|
||||||
|
#get the diagonales function for the receiving widget
|
||||||
|
coef1 = float(vte.allocation.height)/float(vte.allocation.width)
|
||||||
|
coef2 = -float(vte.allocation.height)/float(vte.allocation.width)
|
||||||
|
b1 = 0
|
||||||
|
b2 = vte.allocation.height
|
||||||
|
#determine position in rectangle
|
||||||
|
"""
|
||||||
|
--------
|
||||||
|
|\ /|
|
||||||
|
| \ / |
|
||||||
|
| \/ |
|
||||||
|
| /\ |
|
||||||
|
| / \ |
|
||||||
|
|/ \|
|
||||||
|
--------
|
||||||
|
"""
|
||||||
|
if (x*coef1 + b1 > y ) and (x*coef2 + b2 < y ):
|
||||||
|
pos = "right"
|
||||||
|
if (x*coef1 + b1 > y ) and (x*coef2 + b2 > y ):
|
||||||
|
pos = "top"
|
||||||
|
if (x*coef1 + b1 < y ) and (x*coef2 + b2 > y ):
|
||||||
|
pos = "left"
|
||||||
|
if (x*coef1 + b1 < y ) and (x*coef2 + b2 < y ):
|
||||||
|
pos = "bottom"
|
||||||
|
return pos
|
||||||
|
|
||||||
def add_matches (self, lboundry="[[:<:]]", rboundry="[[:>:]]"):
|
def add_matches (self, lboundry="[[:<:]]", rboundry="[[:>:]]"):
|
||||||
userchars = "-A-Za-z0-9"
|
userchars = "-A-Za-z0-9"
|
||||||
passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'"
|
passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'"
|
||||||
|
@ -220,16 +393,8 @@ class TerminatorTerm (gtk.VBox):
|
||||||
""" Return the current working directory of the subprocess.
|
""" Return the current working directory of the subprocess.
|
||||||
This function requires OS specific behaviours
|
This function requires OS specific behaviours
|
||||||
"""
|
"""
|
||||||
cwd = None
|
|
||||||
system = platform.system ()
|
|
||||||
|
|
||||||
if system == 'Linux':
|
return (pid_get_cwd(self._pid))
|
||||||
try:
|
|
||||||
cwd = os.path.realpath ('/proc/%s/cwd' % self._pid)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return (cwd)
|
|
||||||
|
|
||||||
def reconfigure_vte (self):
|
def reconfigure_vte (self):
|
||||||
# Set our emulation
|
# Set our emulation
|
||||||
|
@ -364,8 +529,8 @@ class TerminatorTerm (gtk.VBox):
|
||||||
self._vte.grab_focus ()
|
self._vte.grab_focus ()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Right mouse button should display a context menu
|
# Right mouse button should display a context menu if ctrl not pressed
|
||||||
if event.button == 3:
|
if event.button == 3 and event.state & gtk.gdk.CONTROL_MASK == 0:
|
||||||
self.do_popup (event)
|
self.do_popup (event)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -434,10 +599,22 @@ class TerminatorTerm (gtk.VBox):
|
||||||
elif keyname == 'S':
|
elif keyname == 'S':
|
||||||
self.do_scrollbar_toggle ()
|
self.do_scrollbar_toggle ()
|
||||||
return (True)
|
return (True)
|
||||||
|
elif keyname == 'T':
|
||||||
|
self.terminator.newtab(self)
|
||||||
|
return (True)
|
||||||
elif keyname in ('Up', 'Down', 'Left', 'Right'):
|
elif keyname in ('Up', 'Down', 'Left', 'Right'):
|
||||||
self.terminator.resizeterm (self, keyname)
|
self.terminator.resizeterm (self, keyname)
|
||||||
return (True)
|
return (True)
|
||||||
|
|
||||||
|
mask = gtk.gdk.CONTROL_MASK
|
||||||
|
if (event.state & mask) == mask:
|
||||||
|
if keyname == 'Page_Down':
|
||||||
|
self.terminator.next_tab(self)
|
||||||
|
return (True)
|
||||||
|
elif keyname == 'Page_Up':
|
||||||
|
self.terminator.previous_tab(self)
|
||||||
|
return (True)
|
||||||
|
|
||||||
if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')):
|
if keyname and (keyname == 'Tab' or keyname.endswith('_Tab')):
|
||||||
if event.state == gtk.gdk.CONTROL_MASK:
|
if event.state == gtk.gdk.CONTROL_MASK:
|
||||||
self.terminator.go_next (self)
|
self.terminator.go_next (self)
|
||||||
|
@ -520,6 +697,8 @@ class TerminatorTerm (gtk.VBox):
|
||||||
item.connect ("toggled", lambda menu_item: self.do_title_toggle ())
|
item.connect ("toggled", lambda menu_item: self.do_title_toggle ())
|
||||||
menu.append (item)
|
menu.append (item)
|
||||||
|
|
||||||
|
self._do_encoding_items (menu)
|
||||||
|
|
||||||
item = gtk.MenuItem ()
|
item = gtk.MenuItem ()
|
||||||
menu.append (item)
|
menu.append (item)
|
||||||
|
|
||||||
|
@ -531,6 +710,10 @@ class TerminatorTerm (gtk.VBox):
|
||||||
item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, True))
|
item.connect ("activate", lambda menu_item: self.terminator.splitaxis (self, True))
|
||||||
menu.append (item)
|
menu.append (item)
|
||||||
|
|
||||||
|
item = gtk.MenuItem (_("Open _Tab"))
|
||||||
|
item.connect ("activate", lambda menu_item: self.terminator.newtab (self))
|
||||||
|
menu.append (item)
|
||||||
|
|
||||||
item = gtk.MenuItem ()
|
item = gtk.MenuItem ()
|
||||||
menu.append (item)
|
menu.append (item)
|
||||||
|
|
||||||
|
@ -548,6 +731,61 @@ class TerminatorTerm (gtk.VBox):
|
||||||
menu.show_all ()
|
menu.show_all ()
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
|
def on_encoding_change (self, widget, encoding):
|
||||||
|
current = self._vte.get_encoding ()
|
||||||
|
if current != encoding:
|
||||||
|
dbg ('Setting Encoding to: %s'%encoding)
|
||||||
|
self._vte.set_encoding (encoding)
|
||||||
|
|
||||||
|
def _do_encoding_items (self, menu):
|
||||||
|
active_encodings = self.conf.active_encodings
|
||||||
|
item = gtk.MenuItem (_("Encodings"))
|
||||||
|
menu.append (item)
|
||||||
|
submenu = gtk.Menu ()
|
||||||
|
item.set_submenu (submenu)
|
||||||
|
|
||||||
|
current_encoding = self._vte.get_encoding ()
|
||||||
|
group = None
|
||||||
|
for encoding in active_encodings:
|
||||||
|
radioitem = gtk.RadioMenuItem (group, _(encoding))
|
||||||
|
if group is None:
|
||||||
|
group = radioitem
|
||||||
|
|
||||||
|
if encoding == current_encoding:
|
||||||
|
radioitem.set_active (True)
|
||||||
|
|
||||||
|
radioitem.connect ('activate', self.on_encoding_change, encoding)
|
||||||
|
submenu.append (radioitem)
|
||||||
|
|
||||||
|
item = gtk.MenuItem (_("Other Encodings"))
|
||||||
|
submenu.append (item)
|
||||||
|
#second level
|
||||||
|
|
||||||
|
submenu = gtk.Menu ()
|
||||||
|
item.set_submenu (submenu)
|
||||||
|
encodings = TerminatorEncoding ().get_list ()
|
||||||
|
encodings.sort (lambda x, y: cmp (x[2].lower (), y[2].lower ()))
|
||||||
|
group = None
|
||||||
|
|
||||||
|
for encoding in encodings:
|
||||||
|
if encoding[1] in active_encodings:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if encoding[1] is None:
|
||||||
|
label = "%s %s"%(encoding[2], self._vte.get_encoding ())
|
||||||
|
else:
|
||||||
|
label = "%s %s"%(encoding[2], encoding[1])
|
||||||
|
|
||||||
|
radioitem = gtk.RadioMenuItem (group, label)
|
||||||
|
if group is None:
|
||||||
|
group = radioitem
|
||||||
|
|
||||||
|
if encoding[1] == current_encoding:
|
||||||
|
radioitem.set_active (True)
|
||||||
|
|
||||||
|
radioitem.connect ('activate', self.on_encoding_change, encoding[1])
|
||||||
|
submenu.append (radioitem)
|
||||||
|
|
||||||
def on_vte_title_change(self, vte):
|
def on_vte_title_change(self, vte):
|
||||||
if self.conf.titletips:
|
if self.conf.titletips:
|
||||||
vte.set_property ("has-tooltip", True)
|
vte.set_property ("has-tooltip", True)
|
||||||
|
@ -555,6 +793,10 @@ class TerminatorTerm (gtk.VBox):
|
||||||
#set the title anyhow, titlebars setting only show/hide the label
|
#set the title anyhow, titlebars setting only show/hide the label
|
||||||
self._title.set_text(vte.get_window_title ())
|
self._title.set_text(vte.get_window_title ())
|
||||||
self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ()))
|
self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ()))
|
||||||
|
notebookpage = self.terminator.get_first_notebook_page(vte)
|
||||||
|
while notebookpage != None:
|
||||||
|
notebookpage[0].set_tab_label_text(notebookpage[1], vte.get_window_title ())
|
||||||
|
notebookpage = self.terminator.get_first_notebook_page(notebookpage[0])
|
||||||
|
|
||||||
def on_vte_focus_in(self, vte, event):
|
def on_vte_focus_in(self, vte, event):
|
||||||
self._titlebox.modify_bg(gtk.STATE_NORMAL,self.terminator.window.get_style().bg[gtk.STATE_SELECTED])
|
self._titlebox.modify_bg(gtk.STATE_NORMAL,self.terminator.window.get_style().bg[gtk.STATE_SELECTED])
|
||||||
|
@ -569,6 +811,13 @@ class TerminatorTerm (gtk.VBox):
|
||||||
def on_vte_focus(self, vte):
|
def on_vte_focus(self, vte):
|
||||||
if vte.get_window_title ():
|
if vte.get_window_title ():
|
||||||
self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ()))
|
self.terminator.set_window_title("%s: %s" %(APP_NAME.capitalize(), vte.get_window_title ()))
|
||||||
|
notebookpage = self.terminator.get_first_notebook_page(vte)
|
||||||
|
while notebookpage != None:
|
||||||
|
notebookpage[0].set_tab_label_text(notebookpage[1], vte.get_window_title ())
|
||||||
|
notebookpage = self.terminator.get_first_notebook_page(notebookpage[0])
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
self._vte.destroy()
|
||||||
|
|
||||||
class Terminator:
|
class Terminator:
|
||||||
def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False):
|
def __init__ (self, profile, command = None, fullscreen = False, maximise = False, borderless = False):
|
||||||
|
@ -580,17 +829,17 @@ class Terminator:
|
||||||
self._fullscreen = False
|
self._fullscreen = False
|
||||||
self.term_list = []
|
self.term_list = []
|
||||||
stores = []
|
stores = []
|
||||||
stores.append (terminatorconfig.TerminatorConfValuestoreRC ())
|
stores.append (config.TerminatorConfValuestoreRC ())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import gconf
|
import gconf
|
||||||
store = terminatorconfig.TerminatorConfValuestoreGConf ()
|
store = config.TerminatorConfValuestoreGConf ()
|
||||||
store.set_reconfigure_callback (self.reconfigure_vtes)
|
store.set_reconfigure_callback (self.reconfigure_vtes)
|
||||||
stores.append (store)
|
stores.append (store)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.conf = terminatorconfig.TerminatorConfig (stores)
|
self.conf = config.TerminatorConfig (stores)
|
||||||
|
|
||||||
self.window = gtk.Window ()
|
self.window = gtk.Window ()
|
||||||
self.window.set_title (APP_NAME.capitalize())
|
self.window.set_title (APP_NAME.capitalize())
|
||||||
|
@ -706,15 +955,18 @@ class Terminator:
|
||||||
self.on_destroy_event (window, gtk.gdk.Event (gtk.gdk.DESTROY))
|
self.on_destroy_event (window, gtk.gdk.Event (gtk.gdk.DESTROY))
|
||||||
|
|
||||||
def set_window_title(self, title):
|
def set_window_title(self, title):
|
||||||
|
"""
|
||||||
|
Modifies Terminator window title
|
||||||
|
"""
|
||||||
self.window.set_title(title)
|
self.window.set_title(title)
|
||||||
|
|
||||||
def splitaxis (self, widget, vertical=True):
|
def add(self, widget, terminal, pos = "bottom"):
|
||||||
""" Split the provided widget on the horizontal or vertical axis. """
|
"""
|
||||||
#should disable splitaxis menu instead?
|
Add a term to another at position pos
|
||||||
if self._fullwindow:
|
"""
|
||||||
return
|
vertical = pos in ("top", "bottom")
|
||||||
|
|
||||||
# create a new terminal and parent pane.
|
# create a new terminal and parent pane.
|
||||||
terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd())
|
|
||||||
pane = (vertical) and gtk.VPaned () or gtk.HPaned ()
|
pane = (vertical) and gtk.VPaned () or gtk.HPaned ()
|
||||||
|
|
||||||
# get the parent of the provided terminal
|
# get the parent of the provided terminal
|
||||||
|
@ -723,15 +975,42 @@ class Terminator:
|
||||||
if isinstance (parent, gtk.Window):
|
if isinstance (parent, gtk.Window):
|
||||||
# We have just one term
|
# We have just one term
|
||||||
widget.reparent (pane)
|
widget.reparent (pane)
|
||||||
|
if pos in ("top", "left"):
|
||||||
pane.pack1 (widget, True, True)
|
pane.remove(widget)
|
||||||
pane.pack2 (terminal, True, True)
|
pane.pack1 (terminal, True, True)
|
||||||
|
pane.pack2 (widget, True, True)
|
||||||
|
else:
|
||||||
|
pane.pack1 (widget, True, True)
|
||||||
|
pane.pack2 (terminal, True, True)
|
||||||
parent.add (pane)
|
parent.add (pane)
|
||||||
|
|
||||||
position = (vertical) and parent.allocation.height \
|
position = (vertical) and parent.allocation.height \
|
||||||
or parent.allocation.width
|
or parent.allocation.width
|
||||||
|
|
||||||
|
if isinstance (parent, gtk.Notebook):
|
||||||
|
page = -1
|
||||||
|
for i in range(0, parent.get_n_pages()):
|
||||||
|
if parent.get_nth_page(i) == widget:
|
||||||
|
page = i
|
||||||
|
break
|
||||||
|
widget.reparent (pane)
|
||||||
|
if pos in ("top", "left"):
|
||||||
|
pane.remove(widget)
|
||||||
|
pane.pack1 (terminal, True, True)
|
||||||
|
pane.pack2 (widget, True, True)
|
||||||
|
else:
|
||||||
|
pane.pack1 (widget, True, True)
|
||||||
|
pane.pack2 (terminal, True, True)
|
||||||
|
#parent.remove_page(page)
|
||||||
|
pane.show()
|
||||||
|
parent.insert_page(pane, None, page)
|
||||||
|
parent.set_tab_label_text(pane, widget._vte.get_window_title())
|
||||||
|
parent.set_tab_label_packing(pane, True, True, gtk.PACK_START)
|
||||||
|
parent.set_current_page(page)
|
||||||
|
|
||||||
|
|
||||||
|
position = (vertical) and parent.allocation.height \
|
||||||
|
or parent.allocation.width
|
||||||
if isinstance (parent, gtk.Paned):
|
if isinstance (parent, gtk.Paned):
|
||||||
# We are inside a split term
|
# We are inside a split term
|
||||||
position = (vertical) and widget.allocation.height \
|
position = (vertical) and widget.allocation.height \
|
||||||
|
@ -744,6 +1023,14 @@ class Terminator:
|
||||||
widget.reparent (pane)
|
widget.reparent (pane)
|
||||||
parent.pack2 (pane, True, True)
|
parent.pack2 (pane, True, True)
|
||||||
|
|
||||||
|
if pos in ("top", "left"):
|
||||||
|
pane.remove(widget)
|
||||||
|
pane.pack1 (terminal, True, True)
|
||||||
|
pane.pack2 (widget, True, True)
|
||||||
|
else:
|
||||||
|
pane.pack1 (widget, True, True)
|
||||||
|
pane.pack2 (terminal, True, True)
|
||||||
|
|
||||||
pane.pack1 (widget, True, True)
|
pane.pack1 (widget, True, True)
|
||||||
pane.pack2 (terminal, True, True)
|
pane.pack2 (terminal, True, True)
|
||||||
|
|
||||||
|
@ -762,7 +1049,75 @@ class Terminator:
|
||||||
|
|
||||||
return (terminal)
|
return (terminal)
|
||||||
|
|
||||||
def closeterm (self, widget):
|
def on_page_reordered(self, notebook, child, page_num):
|
||||||
|
dbg ("Reordered: %d"%page_num)
|
||||||
|
|
||||||
|
def newtab(self,widget):
|
||||||
|
terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd())
|
||||||
|
widgetbox = widget
|
||||||
|
parent = widgetbox.get_parent ()
|
||||||
|
|
||||||
|
if isinstance(parent, gtk.Paned) or isinstance(parent, gtk.Window):
|
||||||
|
#no notebook yet.
|
||||||
|
notebook = gtk.Notebook()
|
||||||
|
notebook.connect('page-reordered',self.on_page_reordered)
|
||||||
|
notebook.set_property('homogeneous', True)
|
||||||
|
notebook.set_tab_reorderable(widgetbox, True)
|
||||||
|
|
||||||
|
if isinstance(parent, gtk.Paned):
|
||||||
|
if parent.get_child1() == widgetbox:
|
||||||
|
widgetbox.reparent(notebook)
|
||||||
|
parent.pack1(notebook)
|
||||||
|
else:
|
||||||
|
widgetbox.reparent(notebook)
|
||||||
|
parent.pack2(notebook)
|
||||||
|
elif isinstance(parent, gtk.Window):
|
||||||
|
widgetbox.reparent(notebook)
|
||||||
|
parent.add(notebook)
|
||||||
|
notebook.set_tab_reorderable(widgetbox,True)
|
||||||
|
notebooklabel = ""
|
||||||
|
if widget._vte.get_window_title() is not None:
|
||||||
|
notebooklabel = widget._vte.get_window_title()
|
||||||
|
notebook.set_tab_label_text(widgetbox, notebooklabel)
|
||||||
|
notebook. set_tab_label_packing(widgetbox, True, True, gtk.PACK_START)
|
||||||
|
notebook.show()
|
||||||
|
elif isinstance(parent, gtk.Notebook):
|
||||||
|
notebook = parent
|
||||||
|
else:
|
||||||
|
return (False)
|
||||||
|
|
||||||
|
notebook.append_page(terminal,terminal._vte.get_window_title())
|
||||||
|
notebook. set_tab_label_packing(terminal, True, True, gtk.PACK_START)
|
||||||
|
notebook.set_tab_reorderable(terminal,True)
|
||||||
|
notebook.set_current_page(-1)
|
||||||
|
index = self.term_list.index(widget)
|
||||||
|
self.term_list.insert (index + 1, terminal)
|
||||||
|
terminal.show ()
|
||||||
|
terminal.spawn_child ()
|
||||||
|
terminal._vte.grab_focus ()
|
||||||
|
return (True)
|
||||||
|
|
||||||
|
|
||||||
|
return terminal
|
||||||
|
|
||||||
|
def splitaxis (self, widget, vertical=True):
|
||||||
|
""" Split the provided widget on the horizontal or vertical axis. """
|
||||||
|
|
||||||
|
#should disable splitaxis menu instead?
|
||||||
|
if self._fullwindow:
|
||||||
|
return
|
||||||
|
|
||||||
|
# create a new terminal and parent pane.
|
||||||
|
terminal = TerminatorTerm (self, self.profile, None, widget.get_cwd())
|
||||||
|
pos = vertical and "bottom" or "right"
|
||||||
|
self.add(widget, terminal, pos)
|
||||||
|
terminal.show ()
|
||||||
|
terminal.spawn_child ()
|
||||||
|
return terminal
|
||||||
|
|
||||||
|
def remove(self, widget):
|
||||||
|
"""Remove a TerminatorTerm from the Terminator view and terms list
|
||||||
|
Returns True on success, False on failure"""
|
||||||
if self._fullwindow:
|
if self._fullwindow:
|
||||||
self.show_back_others(widget)
|
self.show_back_others(widget)
|
||||||
|
|
||||||
|
@ -788,13 +1143,26 @@ class Terminator:
|
||||||
if not sibling:
|
if not sibling:
|
||||||
# something is wrong, give up
|
# something is wrong, give up
|
||||||
print >> sys.stderr, "Error: %s is not a child of %s"%(widget, parent)
|
print >> sys.stderr, "Error: %s is not a child of %s"%(widget, parent)
|
||||||
return
|
return False
|
||||||
|
|
||||||
self.term_list.remove (widget)
|
parent.remove(widget)
|
||||||
grandparent.remove (parent)
|
if isinstance(grandparent, gtk.Notebook):
|
||||||
sibling.reparent (grandparent)
|
page = -1
|
||||||
widget.destroy ()
|
for i in range(0, grandparent.get_n_pages()):
|
||||||
|
if grandparent.get_nth_page(i) == parent:
|
||||||
|
page = i
|
||||||
|
break
|
||||||
|
parent.remove(sibling)
|
||||||
|
grandparent.remove_page(page)
|
||||||
|
grandparent.insert_page(sibling, None,page)
|
||||||
|
grandparent.set_tab_label_packing(sibling, True, True, gtk.PACK_START)
|
||||||
|
|
||||||
|
else:
|
||||||
|
grandparent.remove (parent)
|
||||||
|
sibling.reparent (grandparent)
|
||||||
|
grandparent.resize_children()
|
||||||
parent.destroy ()
|
parent.destroy ()
|
||||||
|
self.term_list.remove (widget)
|
||||||
|
|
||||||
if not isinstance (sibling, gtk.Paned):
|
if not isinstance (sibling, gtk.Paned):
|
||||||
for term in self.term_list:
|
for term in self.term_list:
|
||||||
|
@ -804,10 +1172,39 @@ class Terminator:
|
||||||
else:
|
else:
|
||||||
if index == 0: index = 1
|
if index == 0: index = 1
|
||||||
self.term_list[index - 1]._vte.grab_focus ()
|
self.term_list[index - 1]._vte.grab_focus ()
|
||||||
if len(self.term_list) == 1:
|
elif isinstance (parent, gtk.Notebook):
|
||||||
self.term_list[0]._titlebox.hide()
|
parent.remove(widget)
|
||||||
|
nbpages = parent.get_n_pages()
|
||||||
|
index = self.term_list.index (widget)
|
||||||
|
self.term_list.remove (widget)
|
||||||
|
if nbpages == 1:
|
||||||
|
sibling = parent.get_nth_page(0)
|
||||||
|
parent.remove(sibling)
|
||||||
|
gdparent = parent.get_parent()
|
||||||
|
if isinstance(gdparent, gtk.Window):
|
||||||
|
gdparent.remove(parent)
|
||||||
|
gdparent.add(sibling)
|
||||||
|
elif isinstance(gdparent, gtk.Paned):
|
||||||
|
if gdparent.get_child1() == parent:
|
||||||
|
gdparent.remove(parent)
|
||||||
|
gdparent.pack1(sibling)
|
||||||
|
else:
|
||||||
|
gdparent.remove(parent)
|
||||||
|
gdparent.pack2(sibling)
|
||||||
|
parent.destroy()
|
||||||
|
if index == 0: index = 1
|
||||||
|
self.term_list[index - 1]._vte.grab_focus ()
|
||||||
|
|
||||||
return
|
if len(self.term_list) == 1:
|
||||||
|
self.term_list[0]._titlebox.hide()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def closeterm (self, widget):
|
||||||
|
if self.remove(widget):
|
||||||
|
widget.destroy ()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def go_next (self, term):
|
def go_next (self, term):
|
||||||
current = self.term_list.index (term)
|
current = self.term_list.index (term)
|
||||||
|
@ -818,7 +1215,24 @@ class Terminator:
|
||||||
else:
|
else:
|
||||||
next += 1
|
next += 1
|
||||||
|
|
||||||
self.term_list[next]._vte.grab_focus ()
|
|
||||||
|
nextterm = self.term_list[next]
|
||||||
|
if isinstance(nextterm.get_parent(), gtk.Notebook):
|
||||||
|
box = nextterm
|
||||||
|
parent = box.get_parent()
|
||||||
|
for i in range(0, parent.get_n_pages()):
|
||||||
|
if box == parent.get_nth_page(i):
|
||||||
|
parent.set_current_page(i)
|
||||||
|
break
|
||||||
|
notebookpage = self.get_first_notebook_page(nextterm)
|
||||||
|
if notebookpage:
|
||||||
|
child = None
|
||||||
|
for i in range(0, notebookpage[0].get_n_pages()):
|
||||||
|
if notebookpage[0].get_nth_page(i) == notebookpage[1]:
|
||||||
|
notebookpage[0].set_current_page(i)
|
||||||
|
break
|
||||||
|
nextterm._vte.grab_focus ()
|
||||||
|
|
||||||
|
|
||||||
def go_prev (self, term):
|
def go_prev (self, term):
|
||||||
current = self.term_list.index (term)
|
current = self.term_list.index (term)
|
||||||
|
@ -830,7 +1244,23 @@ class Terminator:
|
||||||
previous -= 1
|
previous -= 1
|
||||||
|
|
||||||
#self.window.set_title(self.term_list[previous]._vte.get_window_title())
|
#self.window.set_title(self.term_list[previous]._vte.get_window_title())
|
||||||
self.term_list[previous]._vte.grab_focus ()
|
previousterm = self.term_list[previous]
|
||||||
|
if isinstance(previousterm.get_parent(), gtk.Notebook):
|
||||||
|
box = previousterm
|
||||||
|
parent = box.get_parent()
|
||||||
|
for i in range(0, parent.get_n_pages()):
|
||||||
|
if box == parent.get_nth_page(i):
|
||||||
|
parent.set_current_page(i)
|
||||||
|
break
|
||||||
|
notebookpage = self.get_first_notebook_page(previousterm)
|
||||||
|
if notebookpage:
|
||||||
|
child = None
|
||||||
|
for i in range(0, notebookpage[0].get_n_pages()):
|
||||||
|
if notebookpage[0].get_nth_page(i) == notebookpage[1]:
|
||||||
|
notebookpage[0].set_current_page(i)
|
||||||
|
break
|
||||||
|
previousterm._vte.grab_focus ()
|
||||||
|
|
||||||
|
|
||||||
def resizeterm (self, widget, keyname):
|
def resizeterm (self, widget, keyname):
|
||||||
vertical = False
|
vertical = False
|
||||||
|
@ -862,6 +1292,24 @@ class Terminator:
|
||||||
|
|
||||||
parent.set_position(move)
|
parent.set_position(move)
|
||||||
|
|
||||||
|
def previous_tab(self, term):
|
||||||
|
notebook = self.get_first_parent_notebook(term)
|
||||||
|
notebook.prev_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
def next_tab(self, term):
|
||||||
|
notebook = self.get_first_parent_notebook(term)
|
||||||
|
notebook.next_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_first_parent_notebook(self, widget):
|
||||||
|
if isinstance (widget, gtk.Window):
|
||||||
|
return None
|
||||||
|
parent = widget.get_parent()
|
||||||
|
if isinstance (parent, gtk.Notebook):
|
||||||
|
return parent
|
||||||
|
return self.get_first_parent_notebook(parent)
|
||||||
|
|
||||||
def get_first_parent_paned (self, widget, vertical = None):
|
def get_first_parent_paned (self, widget, vertical = None):
|
||||||
"""This method returns the first parent pane of a widget.
|
"""This method returns the first parent pane of a widget.
|
||||||
if vertical is True returns the first VPaned
|
if vertical is True returns the first VPaned
|
||||||
|
@ -878,6 +1326,17 @@ class Terminator:
|
||||||
return parent
|
return parent
|
||||||
return self.get_first_parent_paned(parent, vertical)
|
return self.get_first_parent_paned(parent, vertical)
|
||||||
|
|
||||||
|
def get_first_notebook_page(self, widget):
|
||||||
|
if isinstance (widget, gtk.Window):
|
||||||
|
return None
|
||||||
|
parent = widget.get_parent()
|
||||||
|
if isinstance (parent, gtk.Notebook):
|
||||||
|
page = -1
|
||||||
|
for i in range(0, parent.get_n_pages()):
|
||||||
|
if parent.get_nth_page(i) == widget:
|
||||||
|
return (parent, widget)
|
||||||
|
return self.get_first_notebook_page(parent)
|
||||||
|
|
||||||
def reconfigure_vtes (self):
|
def reconfigure_vtes (self):
|
||||||
for term in self.term_list:
|
for term in self.term_list:
|
||||||
term.reconfigure_vte ()
|
term.reconfigure_vte ()
|
||||||
|
@ -915,6 +1374,7 @@ class Terminator:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
def execute_cb (option, opt, value, parser):
|
def execute_cb (option, opt, value, parser):
|
||||||
|
|
|
@ -110,6 +110,8 @@ class TerminatorConfValuestore:
|
||||||
'use_theme_colors' : True,
|
'use_theme_colors' : True,
|
||||||
'http_proxy' : '',
|
'http_proxy' : '',
|
||||||
'ignore_hosts' : ['localhost','127.0.0.0/8','*.local'],
|
'ignore_hosts' : ['localhost','127.0.0.0/8','*.local'],
|
||||||
|
'encoding' : 'UTF-8',
|
||||||
|
'active_encodings' : ['UTF-8', 'ISO-8859-1'],
|
||||||
}
|
}
|
||||||
|
|
||||||
def __getattr__ (self, keyname):
|
def __getattr__ (self, keyname):
|
||||||
|
@ -169,6 +171,10 @@ class TerminatorConfValuestoreGConf (TerminatorConfValuestore):
|
||||||
profile = self.client.get_string (self._gt_dir + '/global/default_profile')
|
profile = self.client.get_string (self._gt_dir + '/global/default_profile')
|
||||||
profiles = self.client.get_list (self._gt_dir + '/global/profile_list','string')
|
profiles = self.client.get_list (self._gt_dir + '/global/profile_list','string')
|
||||||
|
|
||||||
|
#set up the active encoding list
|
||||||
|
self.active_encodings = self.client.get_list (self._gt_dir + '/global/active_encodings', 'string')
|
||||||
|
|
||||||
|
#need to handle the list of Gconf.value
|
||||||
if profile in profiles:
|
if profile in profiles:
|
||||||
dbg (" VSGConf: Found profile '%s' in profile_list"%profile)
|
dbg (" VSGConf: Found profile '%s' in profile_list"%profile)
|
||||||
self.profile = '%s/%s'%(self._profile_dir, profile)
|
self.profile = '%s/%s'%(self._profile_dir, profile)
|
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# TerminatorEncoding - charset encoding classes
|
||||||
|
# Copyright (C) 2006-2008 chantra@debuntu.org
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 2 only.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""TerminatorEncoding by Emmanuel Bretelle <chantra@debuntu.org>
|
||||||
|
|
||||||
|
TerminatorEncoding supplies a list of possible encoding
|
||||||
|
values.
|
||||||
|
This list is taken from gnome-terminal's src/encoding.h
|
||||||
|
and src/encoding.c
|
||||||
|
"""
|
||||||
|
|
||||||
|
class TerminatorEncoding:
|
||||||
|
|
||||||
|
encodings = [
|
||||||
|
[True, None, _("Current Locale")],
|
||||||
|
[False, "ISO-8859-1", _("Western")],
|
||||||
|
[False, "ISO-8859-2", _("Central European")],
|
||||||
|
[False, "ISO-8859-3", _("South European") ],
|
||||||
|
[False, "ISO-8859-4", _("Baltic") ],
|
||||||
|
[False,"ISO-8859-5", _("Cyrillic") ],
|
||||||
|
[False, "ISO-8859-6", _("Arabic") ],
|
||||||
|
[False, "ISO-8859-7", _("Greek") ],
|
||||||
|
[False, "ISO-8859-8", _("Hebrew Visual") ],
|
||||||
|
[False, "ISO-8859-8-I", _("Hebrew") ],
|
||||||
|
[False, "ISO-8859-9", _("Turkish") ],
|
||||||
|
[False, "ISO-8859-10", _("Nordic") ],
|
||||||
|
[False, "ISO-8859-13", _("Baltic") ],
|
||||||
|
[False, "ISO-8859-14", _("Celtic") ],
|
||||||
|
[False, "ISO-8859-15", _("Western") ],
|
||||||
|
[False, "ISO-8859-16", _("Romanian") ],
|
||||||
|
[False, "UTF-7", _("Unicode") ],
|
||||||
|
[False, "UTF-8", _("Unicode") ],
|
||||||
|
[False, "UTF-16", _("Unicode") ],
|
||||||
|
[False, "UCS-2", _("Unicode") ],
|
||||||
|
[False, "UCS-4", _("Unicode") ],
|
||||||
|
[False, "ARMSCII-8", _("Armenian") ],
|
||||||
|
[False, "BIG5", _("Chinese Traditional") ],
|
||||||
|
[False, "BIG5-HKSCS", _("Chinese Traditional") ],
|
||||||
|
[False, "CP866", _("Cyrillic/Russian") ],
|
||||||
|
[False, "EUC-JP", _("Japanese") ],
|
||||||
|
[False, "EUC-KR", _("Korean") ],
|
||||||
|
[False, "EUC-TW", _("Chinese Traditional") ],
|
||||||
|
[False, "GB18030", _("Chinese Simplified") ],
|
||||||
|
[False, "GB2312", _("Chinese Simplified") ],
|
||||||
|
[False, "GBK", _("Chinese Simplified") ],
|
||||||
|
[False, "GEORGIAN-PS", _("Georgian") ],
|
||||||
|
[False, "HZ", _("Chinese Simplified") ],
|
||||||
|
[False, "IBM850", _("Western") ],
|
||||||
|
[False, "IBM852", _("Central European") ],
|
||||||
|
[False, "IBM855", _("Cyrillic") ],
|
||||||
|
[False, "IBM857", _("Turkish") ],
|
||||||
|
[False, "IBM862", _("Hebrew") ],
|
||||||
|
[False, "IBM864", _("Arabic") ],
|
||||||
|
[False, "ISO2022JP", _("Japanese") ],
|
||||||
|
[False, "ISO2022KR", _("Korean") ],
|
||||||
|
[False, "ISO-IR-111", _("Cyrillic") ],
|
||||||
|
[False, "JOHAB", _("Korean") ],
|
||||||
|
[False, "KOI8-R", _("Cyrillic") ],
|
||||||
|
[False, "KOI8-U", _("Cyrillic/Ukrainian") ],
|
||||||
|
[False, "MAC_ARABIC", _("Arabic") ],
|
||||||
|
[False, "MAC_CE", _("Central European") ],
|
||||||
|
[False, "MAC_CROATIAN", _("Croatian") ],
|
||||||
|
[False, "MAC-CYRILLIC", _("Cyrillic") ],
|
||||||
|
[False, "MAC_DEVANAGARI", _("Hindi") ],
|
||||||
|
[False, "MAC_FARSI", _("Persian") ],
|
||||||
|
[False, "MAC_GREEK", _("Greek") ],
|
||||||
|
[False, "MAC_GUJARATI", _("Gujarati") ],
|
||||||
|
[False, "MAC_GURMUKHI", _("Gurmukhi") ],
|
||||||
|
[False, "MAC_HEBREW", _("Hebrew") ],
|
||||||
|
[False, "MAC_ICELANDIC", _("Icelandic") ],
|
||||||
|
[False, "MAC_ROMAN", _("Western") ],
|
||||||
|
[False, "MAC_ROMANIAN", _("Romanian") ],
|
||||||
|
[False, "MAC_TURKISH", _("Turkish") ],
|
||||||
|
[False, "MAC_UKRAINIAN", _("Cyrillic/Ukrainian") ],
|
||||||
|
[False, "SHIFT-JIS", _("Japanese") ],
|
||||||
|
[False, "TCVN", _("Vietnamese") ],
|
||||||
|
[False, "TIS-620", _("Thai") ],
|
||||||
|
[False, "UHC", _("Korean") ],
|
||||||
|
[False, "VISCII", _("Vietnamese") ],
|
||||||
|
[False, "WINDOWS-1250", _("Central European") ],
|
||||||
|
[False, "WINDOWS-1251", _("Cyrillic") ],
|
||||||
|
[False, "WINDOWS-1252", _("Western") ],
|
||||||
|
[False, "WINDOWS-1253", _("Greek") ],
|
||||||
|
[False, "WINDOWS-1254", _("Turkish") ],
|
||||||
|
[False, "WINDOWS-1255", _("Hebrew") ],
|
||||||
|
[False, "WINDOWS-1256", _("Arabic") ],
|
||||||
|
[False, "WINDOWS-1257", _("Baltic") ],
|
||||||
|
[False, "WINDOWS-1258", _("Vietnamese") ]
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_list():
|
||||||
|
return TerminatorEncoding.encodings
|
||||||
|
get_list = staticmethod(get_list)
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/local/bin/python
|
||||||
|
#
|
||||||
|
# Use sysctl() to retrieve the cwd of an arbitrary process on FreeBSD.
|
||||||
|
# Tested on FreeBSD 7-STABLE/amd64 from April 11 2008.
|
||||||
|
#
|
||||||
|
# Be prepared for excitement if the structs are changed.
|
||||||
|
#
|
||||||
|
# Blame: Thomas Hurst <tom@hur.st>
|
||||||
|
#
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
# This is padded awkwardly, see /usr/include/sys/socket.h
|
||||||
|
class sockaddr_storage(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('ss_len', c_char),
|
||||||
|
('ss_family', c_char), # /usr/include/sys/_types.h; _uint8_t
|
||||||
|
('__ss_pad1', c_char * 6), # (sizeof(int64) - sizeof(char) - sizeof(ss_family_t))
|
||||||
|
('__ss_align', c_longlong),
|
||||||
|
('__ss_pad2', c_char * 112), # (128(maxsize) - sizeof(char) - sizeof(ss_family_t) -
|
||||||
|
# sizeof(ss_pad1) - sizeof(int64))
|
||||||
|
]
|
||||||
|
|
||||||
|
# struct kinfo_file, defined in /usr/include/sys/user.h
|
||||||
|
class kinfo_file(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
('kf_structsize', c_int),
|
||||||
|
('kf_type', c_int),
|
||||||
|
('kf_fd', c_int),
|
||||||
|
('kf_ref_count', c_int),
|
||||||
|
('kf_flags', c_int),
|
||||||
|
('kf_offset', c_long), # this is a off_t, a pointer
|
||||||
|
('kf_vnode_type', c_int),
|
||||||
|
('kf_sock_domain', c_int),
|
||||||
|
('kf_sock_type', c_int),
|
||||||
|
('kf_sock_protocol', c_int),
|
||||||
|
('kf_path', c_char * 1024), # PATH_MAX
|
||||||
|
('kf_sa_local', sockaddr_storage),
|
||||||
|
('kf_sa_peer', sockaddr_storage),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_process_cwd(pid):
|
||||||
|
libc = CDLL('libc.so')
|
||||||
|
|
||||||
|
len = c_uint(sizeof(c_uint))
|
||||||
|
ver = c_uint(0)
|
||||||
|
|
||||||
|
if (libc.sysctlbyname('kern.osreldate', byref(ver), byref(len), None, 0) < 0):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# kern.proc.filedesc added for procstat(1) after these __FreeBSD_versions
|
||||||
|
if ver.value < 700104 and ver.value < 800019:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# /usr/include/sys/sysctl.h
|
||||||
|
# CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC
|
||||||
|
oid = (c_uint * 4)(1, 14, 14, pid)
|
||||||
|
|
||||||
|
if libc.sysctl(oid, 4, None, byref(len), None, 0) < 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
buf = c_char_p(" " * len.value)
|
||||||
|
if libc.sysctl(oid, 4, buf, byref(len), None, 0) < 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
kifs = cast(buf, POINTER(kinfo_file))
|
||||||
|
for i in range(0, len.value / sizeof(kinfo_file)):
|
||||||
|
kif = kifs[i]
|
||||||
|
if kif.kf_fd == -1: # KF_FD_TYPE_CWD
|
||||||
|
return kif.kf_path
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import os, sys
|
||||||
|
print " => %d cwd = %s" % (os.getpid(), get_process_cwd(os.getpid()))
|
||||||
|
for pid in sys.argv:
|
||||||
|
try:
|
||||||
|
pid = int(pid)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print " => %d cwd = %s" % (pid, get_process_cwd(pid))
|
||||||
|
|
Loading…
Reference in New Issue