parent
4b36c23942
commit
ad71553553
|
@ -8,37 +8,11 @@ import bufferlist, color, completer, keyinput, method, minibuffer, mode
|
||||||
import util, window
|
import util, window
|
||||||
from point import Point
|
from point import Point
|
||||||
|
|
||||||
def run(buffers, jump_to_line=None, init_mode=None):
|
|
||||||
# save terminal state so we can restore it when the program exits
|
|
||||||
attr = termios.tcgetattr(sys.stdin)
|
|
||||||
keyinput.disable_control_chars()
|
|
||||||
|
|
||||||
retval = 1
|
|
||||||
try:
|
|
||||||
retval = curses.wrapper(run_app, buffers, jump_to_line, init_mode)
|
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
# restore terminal state
|
|
||||||
termios.tcsetattr(sys.stdin, termios.TCSANOW, attr)
|
|
||||||
return retval
|
|
||||||
|
|
||||||
def run_app(stdscr, buffers, jump_to_line=None, init_mode=None):
|
|
||||||
curses.def_shell_mode()
|
|
||||||
a = Application(stdscr, buffers, jump_to_line, init_mode)
|
|
||||||
a.run()
|
|
||||||
|
|
||||||
MAX_ERROR_DISPLAY = 128
|
|
||||||
KILL_RING_LIMIT = 128
|
|
||||||
WORD_LETTERS = list(string.letters + string.digits)
|
|
||||||
ERROR_TIMEOUT = -1
|
|
||||||
#ERROR_TIMEOUT = 2
|
|
||||||
|
|
||||||
class Application(object):
|
class Application(object):
|
||||||
def __init__(self, stdscr, buffers=[], jump_to_line=None, init_mode=None):
|
def __init__(self, stdscr, buffers=[], jump_to_line=None, init_mode=None):
|
||||||
# initalize curses primitives
|
# initalize curses primitives
|
||||||
self.stdscr = stdscr
|
self.stdscr = stdscr
|
||||||
(self.y, self.x) = self.stdscr.getmaxyx()
|
self.y, self.x = self.stdscr.getmaxyx()
|
||||||
|
|
||||||
# initialize some basic stuff
|
# initialize some basic stuff
|
||||||
# a highlighted_range contains three things: (window, start_p, end_p)
|
# a highlighted_range contains three things: (window, start_p, end_p)
|
||||||
|
@ -51,7 +25,15 @@ class Application(object):
|
||||||
self.mini_prompt = ""
|
self.mini_prompt = ""
|
||||||
self.error_string = ""
|
self.error_string = ""
|
||||||
self.error_timestamp = None
|
self.error_timestamp = None
|
||||||
|
self.need_draw = True
|
||||||
self.input = keyinput.Handler()
|
self.input = keyinput.Handler()
|
||||||
|
|
||||||
|
# some constants
|
||||||
|
self.error_timeout = -1
|
||||||
|
self.max_error_len = 192
|
||||||
|
self.max_num_kills = 64
|
||||||
|
self.def_word_letters = string.letters + string.digits
|
||||||
|
|
||||||
# let's prepopulate some default token colors
|
# let's prepopulate some default token colors
|
||||||
self.token_colors = {
|
self.token_colors = {
|
||||||
'comment': ('red', 'default', 'bold'),
|
'comment': ('red', 'default', 'bold'),
|
||||||
|
@ -544,7 +526,8 @@ class Application(object):
|
||||||
self.kill_ring[-1] = self.kill_ring[-1] + s
|
self.kill_ring[-1] = self.kill_ring[-1] + s
|
||||||
else:
|
else:
|
||||||
self.kill_ring.append(s)
|
self.kill_ring.append(s)
|
||||||
if KILL_RING_LIMIT and len(self.kill_ring) > KILL_RING_LIMIT:
|
#if KILL_RING_LIMIT and len(self.kill_ring) > KILL_RING_LIMIT:
|
||||||
|
if self.max_num_kills and len(self.kill_ring) > self.max_num_kills:
|
||||||
self.kill_ring.pop(0)
|
self.kill_ring.pop(0)
|
||||||
def pop_kill(self):
|
def pop_kill(self):
|
||||||
return self.kill_ring.pop(-1)
|
return self.kill_ring.pop(-1)
|
||||||
|
@ -605,16 +588,22 @@ class Application(object):
|
||||||
while i == curses.KEY_RESIZE:
|
while i == curses.KEY_RESIZE:
|
||||||
i = self.win.getch()
|
i = self.win.getch()
|
||||||
self.resize_event()
|
self.resize_event()
|
||||||
|
self.need_draw = True
|
||||||
err = ''
|
err = ''
|
||||||
try:
|
try:
|
||||||
self.input.parse(i)
|
self.input.parse(i)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
err = str(e)
|
err = str(e)
|
||||||
while len(self.input.tokens):
|
|
||||||
|
if self.input.tokens:
|
||||||
|
self.need_draw = True
|
||||||
|
while self.input.tokens:
|
||||||
t = self.input.tokens.pop(0)
|
t = self.input.tokens.pop(0)
|
||||||
self.active_window().mode.handle_token(t)
|
self.active_window().mode.handle_token(t)
|
||||||
|
|
||||||
|
if self.need_draw:
|
||||||
self.draw(err)
|
self.draw(err)
|
||||||
|
self.need_draw = False
|
||||||
|
|
||||||
# clear the error line; it might look confusing to the user
|
# clear the error line; it might look confusing to the user
|
||||||
try:
|
try:
|
||||||
|
@ -667,8 +656,8 @@ class Application(object):
|
||||||
self.resize_event()
|
self.resize_event()
|
||||||
if err:
|
if err:
|
||||||
self.set_error(err)
|
self.set_error(err)
|
||||||
if self.error_timestamp is not None and ERROR_TIMEOUT > 0 and \
|
if self.error_timestamp is not None and self.error_timeout > 0 and \
|
||||||
time.time() - self.error_timestamp > ERROR_TIMEOUT:
|
time.time() - self.error_timestamp > self.error_timeout:
|
||||||
self.clear_error()
|
self.clear_error()
|
||||||
(y, x) = self.stdscr.getmaxyx()
|
(y, x) = self.stdscr.getmaxyx()
|
||||||
if y != self.y or x != self.x:
|
if y != self.y or x != self.x:
|
||||||
|
@ -861,10 +850,10 @@ class Application(object):
|
||||||
def get_minibuffer_lines(self):
|
def get_minibuffer_lines(self):
|
||||||
lines, lines2 = [], []
|
lines, lines2 = [], []
|
||||||
if self.error_string:
|
if self.error_string:
|
||||||
if len(self.error_string) < MAX_ERROR_DISPLAY:
|
if len(self.error_string) < self.max_error_len:
|
||||||
s = self.error_string
|
s = self.error_string
|
||||||
else:
|
else:
|
||||||
s = self.error_string[:MAX_ERROR_DISPLAY] + '...'
|
s = self.error_string[:self.max_error_len] + '...'
|
||||||
elif self.mini_buffer_is_open():
|
elif self.mini_buffer_is_open():
|
||||||
s = self.mini_prompt + self.mini_buffer.lines[0]
|
s = self.mini_prompt + self.mini_buffer.lines[0]
|
||||||
lines2 = self.mini_buffer.lines[1:]
|
lines2 = self.mini_buffer.lines[1:]
|
||||||
|
@ -895,6 +884,11 @@ def open_plain_file(path, name=None, binary=False):
|
||||||
else:
|
else:
|
||||||
raise Exception, "can't open %r; unsupported file type" % path
|
raise Exception, "can't open %r; unsupported file type" % path
|
||||||
|
|
||||||
|
def run_app(stdscr, buffers, jump_to_line=None, init_mode=None):
|
||||||
|
curses.def_shell_mode()
|
||||||
|
a = Application(stdscr, buffers, jump_to_line, init_mode)
|
||||||
|
a.run()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
ciphers = {
|
ciphers = {
|
||||||
'none': open_plain_file,
|
'none': open_plain_file,
|
||||||
|
@ -986,5 +980,17 @@ if __name__ == "__main__":
|
||||||
paths.add(path)
|
paths.add(path)
|
||||||
names.add(name)
|
names.add(name)
|
||||||
|
|
||||||
|
# save terminal state so we can restore it when the program exits
|
||||||
|
attr = termios.tcgetattr(sys.stdin)
|
||||||
|
keyinput.disable_control_chars()
|
||||||
|
|
||||||
# ok, now run our app
|
# ok, now run our app
|
||||||
run(buffers, opts.goto, opts.mode)
|
retval = 1
|
||||||
|
try:
|
||||||
|
retval = curses.wrapper(run_app, buffers, opts.goto, opts.mode)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# restore terminal state
|
||||||
|
termios.tcsetattr(sys.stdin, termios.TCSANOW, attr)
|
||||||
|
sys.exit(retval)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import codecs, datetime, grp, md5, os, pwd, re, sets, shutil, stat, string
|
import codecs, datetime, grp, md5, os, pwd, re, shutil, stat, string
|
||||||
import fcntl, select, pty, threading
|
import fcntl, select, pty, threading
|
||||||
import aes, dirutil, regex, highlight, lex, term
|
import aes, dirutil, regex, highlight, lex, term
|
||||||
from point import Point
|
from point import Point
|
||||||
|
|
|
@ -10,9 +10,10 @@ class XTermBuffer(Buffer, XTerm):
|
||||||
modename = 'pipe'
|
modename = 'pipe'
|
||||||
termtype = 'xterm'
|
termtype = 'xterm'
|
||||||
#termtype = 'vt100'
|
#termtype = 'vt100'
|
||||||
def __init__(self, cmd, args, name=None):
|
def __init__(self, app, cmd, args, name=None):
|
||||||
XTerm.__init__(self)
|
XTerm.__init__(self)
|
||||||
Buffer.__init__(self)
|
Buffer.__init__(self)
|
||||||
|
self.application = app
|
||||||
self._name = name or '*XTerm*'
|
self._name = name or '*XTerm*'
|
||||||
self._pid, self._pty = pty.fork()
|
self._pid, self._pty = pty.fork()
|
||||||
if self._pid == 0:
|
if self._pid == 0:
|
||||||
|
@ -102,6 +103,7 @@ class XTermBuffer(Buffer, XTerm):
|
||||||
if ifd:
|
if ifd:
|
||||||
data = os.read(ifd[0], 1024)
|
data = os.read(ifd[0], 1024)
|
||||||
self.term_receive(data)
|
self.term_receive(data)
|
||||||
|
self.application.need_draw = True
|
||||||
if ofd:
|
if ofd:
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
n = os.write(ofd[0], self._towrite)
|
n = os.write(ofd[0], self._towrite)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import glob, os, pwd, sets
|
import glob, os, pwd
|
||||||
import method, util
|
import method, util
|
||||||
|
|
||||||
def find_common_string(candidates):
|
def find_common_string(candidates):
|
||||||
|
@ -78,7 +78,7 @@ class CommandCompleter(Completer):
|
||||||
def get_candidates(self, s, w=None):
|
def get_candidates(self, s, w=None):
|
||||||
path = os.getenv('PATH')
|
path = os.getenv('PATH')
|
||||||
path_dirs = path.split(':')
|
path_dirs = path.split(':')
|
||||||
candidates = sets.Set()
|
candidates = set()
|
||||||
for d in path_dirs:
|
for d in path_dirs:
|
||||||
if (not os.path.isdir(d) or not os.access(d, os.R_OK)):
|
if (not os.path.isdir(d) or not os.access(d, os.R_OK)):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, regex, util, window
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
@ -216,7 +216,9 @@ class KillRegion(Method):
|
||||||
class Copy(Method):
|
class Copy(Method):
|
||||||
'''Copy the contents of the current line'''
|
'''Copy the contents of the current line'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
w.copy_line()
|
result = w.copy_line()
|
||||||
|
if result is None:
|
||||||
|
w.set_error("Empty kill region")
|
||||||
class CopyRegion(Method):
|
class CopyRegion(Method):
|
||||||
'''Copy the region between the mark and the cursor'''
|
'''Copy the region between the mark and the cursor'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -1017,23 +1019,3 @@ class SetModeTabWidth(Method):
|
||||||
return
|
return
|
||||||
app.modes[mode].tabwidth = vargs['width']
|
app.modes[mode].tabwidth = vargs['width']
|
||||||
w.set_error('Default tab width set to %d' % app.modes[mode].tabwidth)
|
w.set_error('Default tab width set to %d' % app.modes[mode].tabwidth)
|
||||||
|
|
||||||
#class HideRange(Method):
|
|
||||||
# def _execute(self, w, **vargs):
|
|
||||||
# cursor = w.logical_cursor()
|
|
||||||
# if cursor.y < w.mark.y:
|
|
||||||
# y1, y2 = cursor.y, w.mark.y
|
|
||||||
# elif w.mark.y < cursor.y:
|
|
||||||
# y1, y2 = w.mark.y, cursor.y
|
|
||||||
# else:
|
|
||||||
# w.set_error("No line range selected")
|
|
||||||
# w.hide(y1, y2)
|
|
||||||
# w.set_error("Lines %d through %d hidden" % (y1, y2))
|
|
||||||
#class UnhideLine(Method):
|
|
||||||
# def _execute(self, w, **vargs):
|
|
||||||
# cursor = w.logical_cursor()
|
|
||||||
# if w.ishidden(cursor.y):
|
|
||||||
# w.unhide(cursor.y)
|
|
||||||
# w.set_error("Line %d is no longer hidden" % cursor.y)
|
|
||||||
# else:
|
|
||||||
# w.set_error("Line %d is not hidden" % cursor.y)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, regex, util, window
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, lex, regex, util, window
|
import buffer, default, dirutil, lex, regex, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, buffer.about
|
import buffer, buffer.about
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, buffer.console
|
import buffer, buffer.console
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, regex, util, window
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, regex, util, window
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, regex, term, util, window
|
import buffer, default, dirutil, regex, term, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, commands, re, sets, tempfile
|
import os, commands, re, tempfile
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
import buffer, default, dirutil, lex, regex, util, window
|
import buffer, default, dirutil, lex, regex, util, window
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import math, os, sets, string
|
import math, os, string
|
||||||
import color, method
|
import color, method
|
||||||
from lex import Lexer
|
from lex import Lexer
|
||||||
from point import Point
|
from point import Point
|
||||||
|
@ -88,6 +88,7 @@ class Fundamental(Handler):
|
||||||
tabber = None
|
tabber = None
|
||||||
context = None
|
context = None
|
||||||
colors = {}
|
colors = {}
|
||||||
|
word_letters = None
|
||||||
|
|
||||||
# config settings installed/modified by the mode
|
# config settings installed/modified by the mode
|
||||||
config = {}
|
config = {}
|
||||||
|
@ -124,7 +125,7 @@ class Fundamental(Handler):
|
||||||
for val2 in val:
|
for val2 in val:
|
||||||
app.config[key].append(val2)
|
app.config[key].append(val2)
|
||||||
for (key, val) in cls.sconfig.iteritems():
|
for (key, val) in cls.sconfig.iteritems():
|
||||||
app.config.setdefault(key, sets.Set())
|
app.config.setdefault(key, set())
|
||||||
app.config[key].add(val)
|
app.config[key].add(val)
|
||||||
for (key, d) in cls.dconfig.iteritems():
|
for (key, d) in cls.dconfig.iteritems():
|
||||||
app.config.setdefault(key, {})
|
app.config.setdefault(key, {})
|
||||||
|
@ -231,6 +232,10 @@ class Fundamental(Handler):
|
||||||
self.add_bindings('insert-text2', ('C-c M-i',))
|
self.add_bindings('insert-text2', ('C-c M-i',))
|
||||||
self.add_bindings('insert-multiline-text', ('C-c m',))
|
self.add_bindings('insert-multiline-text', ('C-c m',))
|
||||||
|
|
||||||
|
# used for all word operations
|
||||||
|
if not self.word_letters:
|
||||||
|
self.word_letters = w.application.def_word_letters
|
||||||
|
|
||||||
# create all the insert actions for the basic text input
|
# create all the insert actions for the basic text input
|
||||||
for c in string.letters + string.digits + string.punctuation:
|
for c in string.letters + string.digits + string.punctuation:
|
||||||
self.add_binding('insert-string-%s' % c, c)
|
self.add_binding('insert-string-%s' % c, c)
|
||||||
|
@ -259,8 +264,6 @@ class Fundamental(Handler):
|
||||||
c, fg, bg = " ", "red", "default"
|
c, fg, bg = " ", "red", "default"
|
||||||
if cont:
|
if cont:
|
||||||
c = "\\"
|
c = "\\"
|
||||||
if w.hiddenindicator(y):
|
|
||||||
bg = "green"
|
|
||||||
return [RenderString(s=c, attrs=color.build(fg, bg))]
|
return [RenderString(s=c, attrs=color.build(fg, bg))]
|
||||||
def get_lmargin(self, w, y, x, ended=False, cont=False):
|
def get_lmargin(self, w, y, x, ended=False, cont=False):
|
||||||
lm = self.lmargin
|
lm = self.lmargin
|
||||||
|
@ -342,10 +345,10 @@ class Fundamental(Handler):
|
||||||
self.window.application.last_action = act.name
|
self.window.application.last_action = act.name
|
||||||
except ActionError, e:
|
except ActionError, e:
|
||||||
#XYZ: HACK--should fix
|
#XYZ: HACK--should fix
|
||||||
if t not in ('C-]', 'C-g'):
|
if t in ('C-]', 'C-g'):
|
||||||
self.window.set_error(str(e))
|
|
||||||
else:
|
|
||||||
self.window.set_error('Cancelled')
|
self.window.set_error('Cancelled')
|
||||||
|
else:
|
||||||
|
self.window.set_error(str(e))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import re, sets, string
|
import re, string
|
||||||
|
|
||||||
import color, method, minibuffer, mode, searchutil
|
import color, method, minibuffer, mode, searchutil
|
||||||
from point import Point
|
from point import Point
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule, NocasePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, NocasePatternRule
|
from lex import Grammar, PatternRule, RegionRule, NocasePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import os, re, sets, string, sys
|
import os, re, string, sys
|
||||||
import buffer, color, commands, completer, context, default, method, mode, regex, tab
|
import buffer, color, commands, completer, context, default, method, mode, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, \
|
from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, context, default, mode, method, regex, tab, method.introspect
|
import color, completer, context, default, mode, method, regex, tab, method.introspect
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import re, sets, string
|
import re, string
|
||||||
|
|
||||||
import color, method, minibuffer, mode, searchutil
|
import color, method, minibuffer, mode, searchutil
|
||||||
from point import Point
|
from point import Point
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import commands, os.path, sets, string, sys, traceback
|
import commands, os.path, string, sys, traceback
|
||||||
import color, completer, default, mode, method, regex, tab
|
import color, completer, default, mode, method, regex, tab
|
||||||
from point import Point
|
from point import Point
|
||||||
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
from lex import Grammar, PatternRule, RegionRule, OverridePatternRule
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import re, sets, string
|
import re, string
|
||||||
|
|
||||||
import color, method, minibuffer, mode, searchutil
|
import color, method, minibuffer, mode, searchutil
|
||||||
from point import Point
|
from point import Point
|
||||||
|
|
|
@ -123,7 +123,7 @@ class OpenShell(Method):
|
||||||
a = w.application
|
a = w.application
|
||||||
if not a.has_buffer_name('*Shell*'):
|
if not a.has_buffer_name('*Shell*'):
|
||||||
#b = buffer.pipe.PipeBuffer('/bin/bash', [], name="*Shell*", term='xterm')
|
#b = buffer.pipe.PipeBuffer('/bin/bash', [], name="*Shell*", term='xterm')
|
||||||
b = buffer.emul.XTermBuffer('/bin/bash', [], name="*Shell*")
|
b = buffer.emul.XTermBuffer(a, '/bin/bash', [], name="*Shell*")
|
||||||
a.add_buffer(b)
|
a.add_buffer(b)
|
||||||
window.Window(b, a)
|
window.Window(b, a)
|
||||||
b = a.bufferlist.get_buffer_by_name('*Shell*')
|
b = a.bufferlist.get_buffer_by_name('*Shell*')
|
||||||
|
|
174
window.py
174
window.py
|
@ -3,8 +3,6 @@ import color, highlight, regex
|
||||||
from point import Point
|
from point import Point
|
||||||
from render import RenderString
|
from render import RenderString
|
||||||
|
|
||||||
WORD_LETTERS = list(string.letters + string.digits)
|
|
||||||
|
|
||||||
# note about the cursor: the cursor position will insert in front of the
|
# note about the cursor: the cursor position will insert in front of the
|
||||||
# character it highlights. to this end, it needs to be able to highlight behind
|
# character it highlights. to this end, it needs to be able to highlight behind
|
||||||
# the last character on a line. thus, the x coordinate of the (logical) cursor
|
# the last character on a line. thus, the x coordinate of the (logical) cursor
|
||||||
|
@ -26,15 +24,12 @@ class Window(object):
|
||||||
self.application = a
|
self.application = a
|
||||||
self.height = height
|
self.height = height
|
||||||
self.width = width
|
self.width = width
|
||||||
|
|
||||||
self.first = Point(0, 0)
|
self.first = Point(0, 0)
|
||||||
self.last = None
|
self.last = None
|
||||||
self.cursor = Point(0, 0)
|
self.cursor = Point(0, 0)
|
||||||
self.mark = None
|
self.mark = None
|
||||||
self.active_point = None
|
self.active_point = None
|
||||||
self.input_line = ""
|
self.input_line = ""
|
||||||
self.hidden_ranges = {}
|
|
||||||
self.hidden_lines = {}
|
|
||||||
|
|
||||||
if mode_name is not None:
|
if mode_name is not None:
|
||||||
pass
|
pass
|
||||||
|
@ -311,14 +306,14 @@ class Window(object):
|
||||||
x = len(self.buffer.lines[y])
|
x = len(self.buffer.lines[y])
|
||||||
else:
|
else:
|
||||||
x -= 1
|
x -= 1
|
||||||
while (y, x) >= start and self.xy_char(x, y) not in WORD_LETTERS:
|
while (y, x) >= start and self.xy_char(x, y) not in self.mode.word_letters:
|
||||||
if x == 0:
|
if x == 0:
|
||||||
y -= 1
|
y -= 1
|
||||||
x = len(self.buffer.lines[y])
|
x = len(self.buffer.lines[y])
|
||||||
else:
|
else:
|
||||||
x -= 1
|
x -= 1
|
||||||
found_word = False
|
found_word = False
|
||||||
while (y, x) >= start and self.xy_char(x, y) in WORD_LETTERS:
|
while (y, x) >= start and self.xy_char(x, y) in self.mode.word_letters:
|
||||||
found_word = True
|
found_word = True
|
||||||
if x == 0:
|
if x == 0:
|
||||||
y -= 1
|
y -= 1
|
||||||
|
@ -339,13 +334,13 @@ class Window(object):
|
||||||
else:
|
else:
|
||||||
(x, y) = p.xy()
|
(x, y) = p.xy()
|
||||||
end = self.buffer.get_buffer_end()
|
end = self.buffer.get_buffer_end()
|
||||||
while (y, x) < end and self.xy_char(x, y) not in WORD_LETTERS:
|
while (y, x) < end and self.xy_char(x, y) not in self.mode.word_letters:
|
||||||
if x == len(self.buffer.lines[y]):
|
if x == len(self.buffer.lines[y]):
|
||||||
x = 0
|
x = 0
|
||||||
y += 1
|
y += 1
|
||||||
else:
|
else:
|
||||||
x += 1
|
x += 1
|
||||||
while (y, x) < end and self.xy_char(x, y) in WORD_LETTERS:
|
while (y, x) < end and self.xy_char(x, y) in self.mode.word_letters:
|
||||||
if x == len(self.buffer.lines[y]):
|
if x == len(self.buffer.lines[y]):
|
||||||
x = 0
|
x = 0
|
||||||
y += 1
|
y += 1
|
||||||
|
@ -360,27 +355,27 @@ class Window(object):
|
||||||
p = self.find_right_word()
|
p = self.find_right_word()
|
||||||
if p is not None:
|
if p is not None:
|
||||||
self.goto(p)
|
self.goto(p)
|
||||||
def get_word_bounds_at_point(self, p, wl=WORD_LETTERS):
|
def get_word_bounds_at_point(self, p):
|
||||||
if len(self.buffer.lines[p.y]) == 0:
|
if len(self.buffer.lines[p.y]) == 0:
|
||||||
return None
|
return None
|
||||||
elif self.cursor_char() not in wl:
|
elif self.cursor_char() not in wl:
|
||||||
return None
|
return None
|
||||||
x1 = x2 = p.x
|
x1 = x2 = p.x
|
||||||
while x1 > 0 and self.xy_char(x1 - 1, p.y) in wl:
|
while x1 > 0 and self.xy_char(x1 - 1, p.y) in self.mode.word_letters:
|
||||||
x1 -= 1
|
x1 -= 1
|
||||||
while x2 < len(self.buffer.lines[p.y]) and self.xy_char(x2, p.y) in wl:
|
while x2 < len(self.buffer.lines[p.y]) and self.xy_char(x2, p.y) in wl:
|
||||||
x2 += 1
|
x2 += 1
|
||||||
return (Point(x1, p.y), Point(x2, p.y))
|
return (Point(x1, p.y), Point(x2, p.y))
|
||||||
def get_word_at_point(self, p, wl=WORD_LETTERS):
|
def get_word_at_point(self, p):
|
||||||
bounds = self.get_word_bounds_at_point(p, wl)
|
bounds = self.get_word_bounds_at_point(p)
|
||||||
if bounds is None:
|
if bounds is None:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return self.buffer.get_substring(bounds[0], bounds[1])
|
return self.buffer.get_substring(bounds[0], bounds[1])
|
||||||
def get_word_bounds(self, wl=WORD_LETTERS):
|
def get_word_bounds(self):
|
||||||
return self.get_word_bounds_at_point(self.logical_cursor(), wl)
|
return self.get_word_bounds_at_point(self.logical_cursor())
|
||||||
def get_word(self, wl=WORD_LETTERS):
|
def get_word(self):
|
||||||
return self.get_word_at_point(self.logical_cursor(), wl)
|
return self.get_word_at_point(self.logical_cursor())
|
||||||
|
|
||||||
# page up/down
|
# page up/down
|
||||||
def _pshift_up(self, p, num):
|
def _pshift_up(self, p, num):
|
||||||
|
@ -496,69 +491,111 @@ class Window(object):
|
||||||
self.set_mark_point(self.logical_cursor())
|
self.set_mark_point(self.logical_cursor())
|
||||||
self.goto(p)
|
self.goto(p)
|
||||||
|
|
||||||
# deletion
|
# finding (used by deletion, killing, and copying)
|
||||||
def left_delete(self):
|
def get_line(self):
|
||||||
self.buffer.left_delete(self.logical_cursor())
|
(x, y) = self.logical_cursor().xy()
|
||||||
def right_delete(self):
|
lines = self.buffer.lines
|
||||||
self.buffer.right_delete(self.logical_cursor())
|
if y < len(lines) - 1:
|
||||||
def delete(self, p1, p2):
|
return (Point(0, y), Point(0, y + 1))
|
||||||
self.buffer.delete(p1, p2)
|
elif y > 0:
|
||||||
|
return (Point(len(lines[y - 1]), y - 1), Point(len(lines[y]), y))
|
||||||
# killing
|
else:
|
||||||
def kill_line(self):
|
return (None, None)
|
||||||
return self.copy_line(kill=True)
|
def get_line_left(self):
|
||||||
def kill_region(self):
|
cursor = self.logical_cursor()
|
||||||
return self.copy_region(kill=True)
|
(x, y) = cursor.xy()
|
||||||
def kill_left_word(self):
|
lines = self.buffer.lines
|
||||||
p1 = self.find_left_word()
|
if (x > 0) and not regex.whitespace.match(lines[y][:x]):
|
||||||
p2 = self.logical_cursor()
|
return (Point(0, y), cursor)
|
||||||
if p1 == p2:
|
elif y > 0:
|
||||||
return
|
return (Point(len(lines[y - 1]), y - 1), cursor)
|
||||||
return self.kill(p1, p2)
|
else:
|
||||||
def kill_right_word(self):
|
return (None, None)
|
||||||
p1 = self.logical_cursor()
|
def get_line_right(self):
|
||||||
p2 = self.find_right_word()
|
|
||||||
if p1 == p2:
|
|
||||||
return
|
|
||||||
return self.kill(p1, p2)
|
|
||||||
def copy_line(self, kill=False):
|
|
||||||
cursor = self.logical_cursor()
|
cursor = self.logical_cursor()
|
||||||
(x, y) = cursor.xy()
|
(x, y) = cursor.xy()
|
||||||
lines = self.buffer.lines
|
lines = self.buffer.lines
|
||||||
if (x < len(lines[y]) and not regex.whitespace.match(lines[y][x:])):
|
if (x < len(lines[y]) and not regex.whitespace.match(lines[y][x:])):
|
||||||
limit = Point(len(lines[y]), y)
|
return (cursor, Point(len(lines[y]), y))
|
||||||
elif y < len(lines) - 1:
|
elif y < len(lines) - 1:
|
||||||
limit = Point(0, y + 1)
|
return (cursor, Point(0, y + 1))
|
||||||
else:
|
else:
|
||||||
return
|
return (None, None)
|
||||||
if kill:
|
def get_region(self):
|
||||||
return self.kill(cursor, limit)
|
|
||||||
else:
|
|
||||||
return self.copy(cursor, limit)
|
|
||||||
def copy_region(self, kill=False):
|
|
||||||
cursor = self.logical_cursor()
|
cursor = self.logical_cursor()
|
||||||
|
p1, p2 = None, None
|
||||||
if cursor < self.mark:
|
if cursor < self.mark:
|
||||||
p1 = cursor
|
p1 = cursor
|
||||||
p2 = self.mark
|
p2 = self.mark
|
||||||
elif self.mark < cursor:
|
elif self.mark < cursor:
|
||||||
p1 = self.mark
|
p1 = self.mark
|
||||||
p2 = cursor
|
p2 = cursor
|
||||||
|
return (p1, p2)
|
||||||
|
def get_left_word(self):
|
||||||
|
p1 = self.find_left_word()
|
||||||
|
p2 = self.logical_cursor()
|
||||||
|
if p1 == p2:
|
||||||
|
return (None, None)
|
||||||
else:
|
else:
|
||||||
self.input_line = "Empty kill region"
|
return (p1, p2)
|
||||||
return
|
def get_right_word(self):
|
||||||
if kill:
|
p1 = self.logical_cursor()
|
||||||
return self.kill(p1, p2)
|
p2 = self.find_right_word()
|
||||||
|
if p1 == p2:
|
||||||
|
return (None, None)
|
||||||
else:
|
else:
|
||||||
return self.copy(p1, p2)
|
return (p1, p2)
|
||||||
|
|
||||||
|
# deletion
|
||||||
|
def delete(self, p1, p2):
|
||||||
|
self.buffer.delete(p1, p2)
|
||||||
|
def delete_line(self):
|
||||||
|
(p1, p2) = self.get_line_right()
|
||||||
|
if p1 is not None: self.delete(p1, p2)
|
||||||
|
def delete_region(self):
|
||||||
|
(p1, p2) = self.get_region()
|
||||||
|
if p1 is not None: self.delete(p1, p2)
|
||||||
|
def delete_left_word(self):
|
||||||
|
(p1, p2) = self.get_left_word()
|
||||||
|
if p1 is not None: self.delete(p1, p2)
|
||||||
|
def delete_right_word(self):
|
||||||
|
(p1, p2) = self.get_right_word()
|
||||||
|
if p1 is not None: self.delete(p1, p2)
|
||||||
|
def left_delete(self):
|
||||||
|
self.buffer.left_delete(self.logical_cursor())
|
||||||
|
def right_delete(self):
|
||||||
|
self.buffer.right_delete(self.logical_cursor())
|
||||||
|
|
||||||
|
# killing
|
||||||
def kill(self, p1, p2):
|
def kill(self, p1, p2):
|
||||||
killed = self.buffer.get_substring(p1, p2)
|
killed = self.buffer.get_substring(p1, p2)
|
||||||
self.buffer.delete(p1, p2)
|
self.buffer.delete(p1, p2)
|
||||||
self.application.push_kill(killed)
|
self.application.push_kill(killed)
|
||||||
return killed
|
return killed
|
||||||
|
def kill_line(self):
|
||||||
|
(p1, p2) = self.get_line_right()
|
||||||
|
if p1 is not None: self.kill(p1, p2)
|
||||||
|
def kill_region(self):
|
||||||
|
(p1, p2) = self.get_region()
|
||||||
|
if p1 is not None: self.kill(p1, p2)
|
||||||
|
def kill_left_word(self):
|
||||||
|
(p1, p2) = self.get_left_word()
|
||||||
|
if p1 is not None: self.kill(p1, p2)
|
||||||
|
def kill_right_word(self):
|
||||||
|
(p1, p2) = self.get_right_word()
|
||||||
|
if p1 is not None: self.kill(p1, p2)
|
||||||
|
|
||||||
|
# copying
|
||||||
def copy(self, p1, p2):
|
def copy(self, p1, p2):
|
||||||
copied = self.buffer.get_substring(p1, p2)
|
copied = self.buffer.get_substring(p1, p2)
|
||||||
self.application.push_kill(copied)
|
self.application.push_kill(copied)
|
||||||
return copied
|
return copied
|
||||||
|
def copy_line(self):
|
||||||
|
(p1, p2) = self.get_line_right()
|
||||||
|
if p1 is not None: return self.copy(p1, p2)
|
||||||
|
def copy_region(self, kill=False):
|
||||||
|
(p1, p2) = self.get_region()
|
||||||
|
if p1 is not None: return self.copy(p1, p2)
|
||||||
|
|
||||||
# overwriting
|
# overwriting
|
||||||
def overwrite_char_at_cursor(self, c):
|
def overwrite_char_at_cursor(self, c):
|
||||||
|
@ -610,31 +647,6 @@ class Window(object):
|
||||||
else:
|
else:
|
||||||
return self.buffer.lines[y][x]
|
return self.buffer.lines[y][x]
|
||||||
|
|
||||||
# hiding stuff
|
|
||||||
def hide(self, y1, y2):
|
|
||||||
if y2 == 0:
|
|
||||||
return
|
|
||||||
for (py1, py2) in self.hidden_ranges.itervalues():
|
|
||||||
if ((y1 >= py1 and y1 < py2) or
|
|
||||||
(y2 >= py1 and y2 < py2) or
|
|
||||||
(y1 <= py1 and y2 >= py2)):
|
|
||||||
return
|
|
||||||
for i in range(y1, y2):
|
|
||||||
self.hidden_lines[i] = y2
|
|
||||||
self.hidden_ranges[y2] = (y1, y2)
|
|
||||||
def ishidden(self, y):
|
|
||||||
return self.hidden_lines.setdefault(y, False)
|
|
||||||
def hiddenindicator(self, y):
|
|
||||||
return y in self.hidden_ranges
|
|
||||||
def unhide(self, y):
|
|
||||||
py2 = self.ishidden(y)
|
|
||||||
if not py2:
|
|
||||||
return
|
|
||||||
py1 = self.hidden_ranges[py2][0]
|
|
||||||
del self.hidden_ranges[py2]
|
|
||||||
for i in range(py1, py2):
|
|
||||||
self.hidden_lines[i] = False
|
|
||||||
|
|
||||||
# undo/redo
|
# undo/redo
|
||||||
def undo(self):
|
def undo(self):
|
||||||
p = self.buffer.undo()
|
p = self.buffer.undo()
|
||||||
|
|
Loading…
Reference in New Issue