Permalink
Browse files

terminal.py: From now on when you resize a terminal it will no longer…

… reduce the width of existing lines to fit within self.cols. Having said that, if a newline is encountered on an existing line that has a width greater than self.cols that line *will* be resized to fit. This should allow for dynamically resizing terminal windows that contain long (browser-wrapped) lines while also allowing applications like 'top' to function properly.

gateone.js:  Tweaked things a bit related to resizing to make sure that terminals stay scrolled to the bottom.
termio.py:  Moved 'import signal' to the top of the file.  Other parts of Gate One use the signal module all the time so it isn't really a benefit to load it dynamically.
termio.py:  Added signal.SIGWINCH back to the code (uncommented it).  Testing from long ago revealed problems but the logic inside termio.Multiplex() has changed considerably since then and tests have shown it to be reliable in the current code base.
  • Loading branch information...
1 parent 9ee0724 commit 8f8664c73ffa5f5f3076697b1238cd08076478c6 @liftoff committed Oct 9, 2012
Showing with 28 additions and 19 deletions.
  1. +1 −1 gateone/plugins/ssh/ssh.py
  2. +1 −0 gateone/static/gateone.js
  3. +1 −2 gateone/templates/index.html
  4. +23 −12 gateone/terminal.py
  5. +2 −4 gateone/termio.py
@@ -985,7 +985,7 @@ def opt_esc_handler(text, tws):
information to duplicate sessions (if the user so desires). For reference,
the specific string which will call this function from a terminal app is::
- \x1b]_;ssh|<whatever>\x07
+ \\x1b]_;ssh|<whatever>\x07
.. seealso:: :class:`gateone.TerminalWebSocket.esc_opt_handler` and :func:`terminal.Terminal._opt_handler`
"""
@@ -721,6 +721,7 @@ var go = GateOne.Base.update(GateOne, {
go.Visual.applyTransform(termPre, transform);
}
}
+ u.scrollToBottom(termPre);
}, 750);
}
window.onresize = onResizeEvent;
@@ -30,6 +30,5 @@
// NOTE: Fonts *and* icons will be scaled according to the fontSize property.
}
</script>
-
</body>
-</html>
+</html>
View
@@ -1048,8 +1048,11 @@ def resize(self, rows, cols, em_dimensions=None):
return # Nothing to do--don't mess with the margins or the cursor
if rows < self.rows: # Remove rows from the top
for i in xrange(self.rows - rows):
- self.screen.pop(0)
- self.renditions.pop(0)
+ line = self.screen.pop(0)
+ # Add it to the scrollback buffer so it isn't lost forever
+ self.scrollback_buf.append(line)
+ rend = self.renditions.pop(0)
+ self.scrollback_renditions.append(rend)
elif rows > self.rows: # Add rows at the bottom
for i in xrange(rows - self.rows):
line = array('u', u' ' * self.cols)
@@ -1059,16 +1062,10 @@ def resize(self, rows, cols, em_dimensions=None):
self.rows = rows
self.top_margin = 0
self.bottom_margin = self.rows - 1
-
# Fix the cursor location:
if self.cursorY >= self.rows:
self.cursorY = self.rows - 1
-
- if cols < self.cols: # Remove cols to the right
- for i in xrange(self.rows):
- self.screen[i] = self.screen[i][:cols - self.cols]
- self.renditions[i] = self.renditions[i][:cols - self.cols]
- elif cols > self.cols: # Add cols to the right
+ if cols > self.cols: # Add cols to the right
for i in xrange(self.rows):
for j in xrange(cols - self.cols):
self.screen[i].append(u' ')
@@ -1497,9 +1494,9 @@ def scroll_up(self, n=1):
empty_line = array('u', u' ' * self.cols) # Line full of spaces
# Add it to the bottom of the window:
self.screen.insert(self.bottom_margin, empty_line)
- # Remove top line's style information
- style = self.renditions.pop(self.top_margin)
- self.scrollback_renditions.append(style)
+ # Remove top line's rendition information
+ rend = self.renditions.pop(self.top_margin)
+ self.scrollback_renditions.append(rend)
# Insert a new empty rendition as well:
empty_line = array('u', unichr(1000) * self.cols)
self.renditions.insert(self.bottom_margin, empty_line)
@@ -1648,6 +1645,7 @@ def newline(self):
if that action will move the curor past :attr:`self.bottom_margin`
(usually the bottom of the screen).
"""
+ cols = self.cols
self.cursorY += 1
# Do CR with every NL because that's how every other terminal emulator
# seems to do it
@@ -1656,6 +1654,19 @@ def newline(self):
self.scroll_up()
self.cursorY = self.bottom_margin
self.clear_line()
+ # Shorten the line if it is longer than the number of columns
+ # NOTE: This lets us keep the width of existing lines even if the number
+ # of columns is reduced while at the same time accounting for apps like
+ # 'top' that merely overwrite existing lines. If we didn't do this
+ # the output from 'top' would get all messed up from leftovers at the
+ # tail end of every line when self.cols had a larger value.
+ if len(self.screen[self.cursorY]) >= cols:
+ self.screen[self.cursorY] = self.screen[self.cursorY][:cols]
+ self.renditions[self.cursorY] = self.renditions[self.cursorY][:cols]
+ # NOTE: The above logic is placed inside of this function instead of
+ # inside self.write() in order to reduce CPU utilization. There's no
+ # point in performing a conditional check for every incoming character
+ # when the only time it will matter is when a newline is being written.
def carriage_return(self):
"""
View
@@ -96,7 +96,7 @@ def set_title():
"""
# Stdlib imports
-import os, sys, time, struct, io, gzip, re, logging
+import os, sys, time, struct, io, gzip, re, logging, signal
from copy import copy
from datetime import timedelta, datetime
from functools import partial
@@ -1386,10 +1386,9 @@ def resize(self, rows, cols, em_dimensions=None, ctrl_l=True):
except IOError:
# Process already ended--no big deal
return
+ os.kill(self.pid, signal.SIGWINCH) # Send the resize signal
if ctrl_l:
self.write(u'\x0c') # ctrl-l
- # SIGWINCH has been disabled since it can screw things up
- #os.kill(self.pid, signal.SIGWINCH) # Send the resize signal
def terminate(self):
"""
@@ -1431,7 +1430,6 @@ def terminate(self):
del self.scheduler
try:
# TODO: Make this walk the series from SIGINT to SIGKILL
- import signal
#os.kill(self.pid, signal.SIGINT)
os.kill(self.pid, signal.SIGTERM)
#os.kill(self.pid, signal.SIGKILL)

0 comments on commit 8f8664c

Please sign in to comment.