1
0
mirror of https://github.com/akelge/zsh synced 2025-07-04 13:39:07 +00:00

Added GetLatestScript update plugin and updated all plugins

This commit is contained in:
2013-01-17 12:18:17 +00:00
parent d9013ec2da
commit 4873c64f28
54 changed files with 10380 additions and 4761 deletions

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque.py {{{
# FILE: autoload/conque_term/conque.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,29 +25,33 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""
Vim terminal emulator.
The Conque does two things. First, it handles communication between Vim and
the terminal/console subprocess. For example, Vim uses the Conque.write()
method to send input, and Conque.read() to update the terminal buffer.
This class is the main interface between Vim and the terminal application. It
handles both updating the Vim buffer with new output and accepting new keyboard
input from the Vim user.
Second, the Conque class handles Unix terminal escape sequence parsing.
Although this class was originally designed for a Unix terminal environment, it
has been extended by the ConqueSole class for Windows.
Usage:
term = Conque()
term.open('/bin/bash', {'TERM': 'vt100'})
term.write("ls -lha\r")
term.read()
term.close()
"""
import vim
import re
import math
import time # DEBUG
class Conque:
# CLASS PROPERTIES {{{
# screen object
screen = None
@ -86,6 +90,12 @@ class Conque:
# color history
color_history = {}
# color highlight cache
highlight_groups = {}
# prune terminal colors
color_pruning = True
# don't wrap table output
unwrap_tables = True
@ -101,15 +111,23 @@ class Conque:
# used for auto_read actions
read_count = 0
# }}}
# input buffer, array of ordinals
input_buffer = []
# constructor
def __init__(self): # {{{
def open(self):
""" Start program and initialize this instance.
Arguments:
command -- Command string to execute, e.g. '/bin/bash --login'
options -- Dictionary of environment vars to set and other options.
"""
# get arguments
command = vim.eval('command')
options = vim.eval('options')
# create terminal screen instance
self.screen = ConqueScreen()
# }}}
# start program and initialize this instance
def open(self, command, options): # {{{
# int vars
self.columns = vim.current.window.width
@ -118,8 +136,12 @@ class Conque:
self.working_lines = vim.current.window.height
self.bottom = vim.current.window.height
# offset first line to make room for startup messages
if int(options['offset']) > 0:
self.l = int(options['offset'])
# init color
self.enable_colors = options['color']
self.enable_colors = options['color'] and not CONQUE_FAST_MODE
# init tabstops
self.init_tabstops()
@ -130,11 +152,15 @@ class Conque:
# send window size signal, in case LINES/COLUMNS is ignored
self.update_window_size(True)
# }}}
# write to pty
def write(self, input, set_cursor=True, read=True): # {{{
def write(self, input, set_cursor=True, read=True):
""" Write a unicode string to the subprocess.
set_cursor -- Position the cursor in the current buffer when finished
read -- Check program for new output when finished
"""
# check if window size has changed
if read:
self.update_window_size()
@ -146,11 +172,40 @@ class Conque:
if read:
self.read(1, set_cursor)
# }}}
# convert latin-1 input into utf-8
# XXX - this is a hack, to be removed soon
def write_latin1(self, input, set_cursor=True, read=True): # {{{
def write_ord(self, input, set_cursor=True, read=True):
""" Write a single character to the subprocess, using an unicode ordinal. """
if CONQUE_PYTHON_VERSION == 2:
self.write(unichr(input), set_cursor, read)
else:
self.write(chr(input), set_cursor, read)
def write_expr(self, expr, set_cursor=True, read=True):
""" Write the value of a Vim expression to the subprocess. """
if CONQUE_PYTHON_VERSION == 2:
try:
val = vim.eval(expr)
self.write(unicode(val, CONQUE_VIM_ENCODING, 'ignore'), set_cursor, read)
except:
pass
else:
try:
# XXX - Depending on Vim to deal with encoding, sadly
self.write(vim.eval(expr), set_cursor, read)
except:
pass
def write_latin1(self, input, set_cursor=True, read=True):
""" Write latin-1 string to conque. Very ugly, shood be removed. """
# XXX - this whole method is a hack, to be removed soon
if CONQUE_PYTHON_VERSION == 2:
try:
@ -161,19 +216,34 @@ class Conque:
else:
self.write(input, set_cursor, read)
# }}}
# read from pty, and update buffer
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): # {{{
def write_buffered_ord(self, chr):
""" Add character ordinal to input buffer. In case we're not allowed to modify buffer a time of input. """
self.input_buffer.append(chr)
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True):
""" Read new output from the subprocess and update the Vim buffer.
Arguments:
timeout -- Milliseconds to wait before reading input
set_cursor -- Set the cursor position in the current buffer when finished
return_output -- Return new subprocess STDOUT + STDERR as a string
update_buffer -- Update the current Vim buffer with the new output
This method goes through the following rough steps:
1. Get new output from subprocess
2. Split output string into control codes, escape sequences, or plain text
3. Loop over and process each chunk, updating the Vim buffer as we go
"""
output = ''
# this may not actually work
try:
# read from subprocess
# read from subprocess and strip null characters
output = self.proc.read(timeout)
# and strip null chars
output = output.replace(chr(0), '')
if output == '':
return
@ -184,19 +254,19 @@ class Conque:
# strip null characters. I'm still not sure why they appear
output = output.replace(chr(0), '')
# split input into individual escape sequences, control codes, and text output
chunks = CONQUE_SEQ_REGEX.split(output)
# don't go through all the csi regex if length is one (no matches)
# if there were no escape sequences, skip processing and treat entire string as plain text
if len(chunks) == 1:
self.plain_text(chunks[0])
# loop through and process escape sequences
else:
for s in chunks:
if s == '':
@ -205,8 +275,7 @@ class Conque:
# Check for control character match {{{
# Check for control character match
if CONQUE_SEQ_REGEX_CTL.match(s[0]):
nr = ord(s[0])
@ -215,9 +284,8 @@ class Conque:
else:
pass
# }}}
# check for escape sequence match {{{
# check for escape sequence match
elif CONQUE_SEQ_REGEX_CSI.match(s):
if s[-1] in CONQUE_ESCAPE:
@ -227,15 +295,13 @@ class Conque:
else:
pass
# }}}
# check for title match {{{
# check for title match
elif CONQUE_SEQ_REGEX_TITLE.match(s):
self.change_title(s[2], s[4:-1])
# }}}
# check for hash match {{{
# check for hash match
elif CONQUE_SEQ_REGEX_HASH.match(s):
if s[-1] in CONQUE_ESCAPE_HASH:
@ -243,9 +309,8 @@ class Conque:
else:
pass
# }}}
# check for charset match {{{
# check for charset match
elif CONQUE_SEQ_REGEX_CHAR.match(s):
if s[-1] in CONQUE_ESCAPE_CHARSET:
@ -253,9 +318,8 @@ class Conque:
else:
pass
# }}}
# check for other escape match {{{
# check for other escape match
elif CONQUE_SEQ_REGEX_ESC.match(s):
if s[-1] in CONQUE_ESCAPE_PLAIN:
@ -263,23 +327,21 @@ class Conque:
else:
pass
# }}}
# else process plain text {{{
# else process plain text
else:
self.plain_text(s)
# }}}
# check window size
# set cusor position
if set_cursor:
self.screen.set_cursor(self.l, self.c)
# we need to set the cursor position
self.cursor_set = False
vim.command('redraw')
# redraw screen for immediate feedback
#if not CONQUE_FAST_MODE:
# vim.command('redraw')
except:
@ -290,19 +352,42 @@ class Conque:
if CONQUE_PYTHON_VERSION == 3:
return output
else:
return output.encode(vim.eval('&encoding'), 'replace')
# }}}
return output.encode(CONQUE_VIM_ENCODING, 'replace')
# for polling
def auto_read(self): # {{{
def auto_read(self):
""" Poll program for more output.
Since Vim doesn't have a reliable event system that can be triggered when new
output is available, we have to continually poll the subprocess instead. This
method is called many times a second when the terminal buffer is active, so it
needs to be very fast and efficient.
The feedkeys portion is required to reset Vim's timer system. The timer is used
to execute this command, typically set to go off after 50 ms of inactivity.
"""
# process buffered input if any
if len(self.input_buffer):
for chr in self.input_buffer:
self.write_ord(chr, set_cursor=False, read=False)
self.input_buffer = []
self.read(1)
# check subprocess status, but not every time since it's CPU expensive
if self.read_count == 10:
if self.read_count % 32 == 0:
if not self.proc.is_alive():
vim.command('call conque_term#get_instance().close()')
return
else:
if self.read_count > 512:
self.read_count = 0
# trim color history occasionally if desired
if self.enable_colors and self.color_pruning:
self.prune_colors()
# ++
self.read_count += 1
# read output
@ -327,17 +412,22 @@ class Conque:
pass
self.cursor_set = True
# }}}
###############################################################################################
# Plain text # {{{
def plain_text(self, input):
""" Write text output to Vim buffer.
# translate input into correct character set
This method writes a string of characters without any control characters or escape sequences
to the Vim buffer. In simple terms, it writes the input string to the buffer starting at the
current cursor position, wrapping the text to a new line if needed. It also triggers the
terminal coloring methods if needed.
"""
# translate input into graphics character set if needed
if self.character_set == 'graphics':
old_input = input
input = ''
input = u('')
for i in range(0, len(old_input)):
chrd = ord(old_input[i])
@ -347,19 +437,23 @@ class Conque:
input = input + old_input[i]
else:
input = input + unichr(CONQUE_GRAPHICS_SET[chrd])
input = input + uchr(CONQUE_GRAPHICS_SET[chrd])
except:
pass
# get current line from Vim buffer
current_line = self.screen[self.l]
if len(current_line) < self.working_columns:
# pad current line with spaces, if it's shorter than cursor position
if len(current_line) < self.c:
current_line = current_line + ' ' * (self.c - len(current_line))
# if line is wider than screen
if self.c + len(input) - 1 > self.working_columns:
# Table formatting hack
if self.unwrap_tables and CONQUE_TABLE_OUTPUT.match(input):
self.screen[self.l] = current_line[:self.c - 1] + input + current_line[self.c + len(input) - 1:]
@ -367,7 +461,9 @@ class Conque:
self.c += len(input)
return
diff = self.c + len(input) - self.working_columns - 1
# if autowrap is enabled
if self.autowrap:
self.screen[self.l] = current_line[:self.c - 1] + input[:-1 * diff]
@ -388,7 +484,21 @@ class Conque:
self.apply_color(self.c, self.c + len(input))
self.c += len(input)
def apply_color(self, start, end, line=0):
""" Apply terminal colors to buffer for a range of characters in a single line.
When a text attribute escape sequence is encountered during input processing, the
attributes are recorded in the dictionary self.color_changes. After those attributes
have been applied, the changes are recorded in a second dictionary self.color_history.
This method inspects both dictionaries to calculate any syntax highlighting
that needs to be executed to render the text attributes in the Vim buffer.
"""
# stop here if coloration is disabled
@ -397,16 +507,16 @@ class Conque:
# allow custom line nr to be passed
if line:
real_line = line
buffer_line = line
else:
real_line = self.screen.get_real_line(self.l)
buffer_line = self.get_buffer_line(self.l)
# check for previous overlapping coloration
to_del = []
if real_line in self.color_history:
for i in range(len(self.color_history[real_line])):
syn = self.color_history[real_line][i]
if buffer_line in self.color_history:
for i in range(len(self.color_history[buffer_line])):
syn = self.color_history[buffer_line][i]
if syn['start'] >= start and syn['start'] < end:
@ -415,7 +525,7 @@ class Conque:
# outside
if syn['end'] > end:
self.exec_highlight(real_line, end, syn['end'], syn['highlight'])
self.exec_highlight(buffer_line, end, syn['end'], syn['highlight'])
elif syn['end'] > start and syn['end'] <= end:
vim.command('syn clear ' + syn['name'])
@ -423,47 +533,83 @@ class Conque:
# outside
if syn['start'] < start:
self.exec_highlight(real_line, syn['start'], start, syn['highlight'])
self.exec_highlight(buffer_line, syn['start'], start, syn['highlight'])
# remove overlapped colors
if len(to_del) > 0:
to_del.reverse()
for di in to_del:
del self.color_history[real_line][di]
del self.color_history[buffer_line][di]
# if there are no new colors
if len(self.color_changes) == 0:
return
# build the color attribute string
highlight = ''
for attr in self.color_changes.keys():
highlight = highlight + ' ' + attr + '=' + self.color_changes[attr]
# execute the highlight
self.exec_highlight(real_line, start, end, highlight)
self.exec_highlight(buffer_line, start, end, highlight)
def exec_highlight(self, buffer_line, start, end, highlight):
""" Execute the Vim commands for a single syntax highlight """
syntax_name = 'ConqueHighLightAt_%d_%d_%d_%d' % (self.proc.pid, self.l, start, len(self.color_history) + 1)
syntax_options = 'contains=ALLBUT,ConqueString,MySQLString,MySQLKeyword oneline'
syntax_region = 'syntax match %s /\%%%dl\%%>%dc.\{%d}\%%<%dc/ %s' % (syntax_name, buffer_line, start - 1, end - start, end + 1, syntax_options)
# check for cached highlight group
hgroup = 'ConqueHL_%d' % (abs(hash(highlight)))
if hgroup not in self.highlight_groups:
syntax_group = 'highlight %s %s' % (hgroup, highlight)
self.highlight_groups[hgroup] = hgroup
vim.command(syntax_group)
# link this syntax match to existing highlight group
syntax_highlight = 'highlight link %s %s' % (syntax_name, self.highlight_groups[hgroup])
def exec_highlight(self, real_line, start, end, highlight):
unique_key = str(self.proc.pid)
syntax_name = 'EscapeSequenceAt_' + unique_key + '_' + str(self.l) + '_' + str(start) + '_' + str(len(self.color_history) + 1)
syntax_options = ' contains=ALLBUT,ConqueString,MySQLString,MySQLKeyword oneline'
syntax_region = 'syntax match ' + syntax_name + ' /\%' + str(real_line) + 'l\%>' + str(start - 1) + 'c.*\%<' + str(end + 1) + 'c/' + syntax_options
syntax_highlight = 'highlight ' + syntax_name + highlight
vim.command(syntax_region)
vim.command(syntax_highlight)
# add syntax name to history
if not real_line in self.color_history:
self.color_history[real_line] = []
if not buffer_line in self.color_history:
self.color_history[buffer_line] = []
self.color_history[buffer_line].append({'name': syntax_name, 'start': start, 'end': end, 'highlight': highlight})
def prune_colors(self):
""" Remove old syntax highlighting from the Vim buffer
The kind of syntax highlighting required for terminal colors can make
Conque run slowly. The prune_colors() method will remove old highlight definitions
to keep the maximum number of highlight rules within a reasonable range.
"""
buffer_line = self.get_buffer_line(self.l)
ks = list(self.color_history.keys())
for line in ks:
if line < buffer_line - CONQUE_MAX_SYNTAX_LINES:
for syn in self.color_history[line]:
vim.command('syn clear ' + syn['name'])
del self.color_history[line]
self.color_history[real_line].append({'name': syntax_name, 'start': start, 'end': end, 'highlight': highlight})
# }}}
###############################################################################################
# Control functions {{{
# Control functions
def ctl_nl(self):
""" Process the newline control character. """
# if we're in a scrolling region, scroll instead of moving cursor down
if self.lines != self.working_lines and self.l == self.bottom:
del self.screen[self.top]
@ -476,24 +622,29 @@ class Conque:
self.color_changes = {}
def ctl_cr(self):
""" Process the carriage return control character. """
self.c = 1
self.color_changes = {}
def ctl_bs(self):
""" Process the backspace control character. """
if self.c > 1:
self.c += -1
def ctl_soh(self):
""" Process the start of heading control character. """
pass
def ctl_stx(self):
pass
def ctl_bel(self):
""" Process the bell control character. """
vim.command('call conque_term#bell()')
def ctl_tab(self):
""" Process the tab control character. """
# default tabstop location
ts = self.working_columns
@ -508,17 +659,20 @@ class Conque:
self.c = ts
def ctl_so(self):
""" Process the shift out control character. """
self.character_set = 'graphics'
def ctl_si(self):
""" Process the shift in control character. """
self.character_set = 'ascii'
# }}}
###############################################################################################
# CSI functions {{{
# CSI functions
def csi_font(self, csi): # {{{
def csi_font(self, csi):
""" Process the text attribute escape sequence. """
if not self.enable_colors:
return
@ -557,9 +711,10 @@ class Conque:
self.color_changes[attr] += ',' + CONQUE_FONT[val]['attributes'][attr]
else:
self.color_changes[attr] = CONQUE_FONT[val]['attributes'][attr]
# }}}
def csi_clear_line(self, csi): # {{{
def csi_clear_line(self, csi):
""" Process the line clear escape sequence. """
# this escape defaults to 0
@ -583,16 +738,17 @@ class Conque:
# clear colors
if csi['val'] == 2 or (csi['val'] == 0 and self.c == 1):
real_line = self.screen.get_real_line(self.l)
if real_line in self.color_history:
for syn in self.color_history[real_line]:
buffer_line = self.get_buffer_line(self.l)
if buffer_line in self.color_history:
for syn in self.color_history[buffer_line]:
vim.command('syn clear ' + syn['name'])
# }}}
def csi_cursor_right(self, csi): # {{{
def csi_cursor_right(self, csi):
""" Process the move cursor right escape sequence. """
# we use 1 even if escape explicitly specifies 0
if csi['val'] == 0:
csi['val'] = 1
@ -606,9 +762,10 @@ class Conque:
return
self.c = self.bound(self.c + csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_left(self, csi): # {{{
def csi_cursor_left(self, csi):
""" Process the move cursor left escape sequence. """
# we use 1 even if escape explicitly specifies 0
if csi['val'] == 0:
csi['val'] = 1
@ -619,25 +776,29 @@ class Conque:
return
self.c = self.bound(self.c - csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_to_column(self, csi): # {{{
def csi_cursor_to_column(self, csi):
""" Process the move cursor to column escape sequence. """
self.c = self.bound(csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_up(self, csi): # {{{
def csi_cursor_up(self, csi):
""" Process the move cursor up escape sequence. """
self.l = self.bound(self.l - csi['val'], self.top, self.bottom)
self.color_changes = {}
# }}}
def csi_cursor_down(self, csi): # {{{
def csi_cursor_down(self, csi):
""" Process the move cursor down escape sequence. """
self.l = self.bound(self.l + csi['val'], self.top, self.bottom)
self.color_changes = {}
# }}}
def csi_clear_screen(self, csi): # {{{
def csi_clear_screen(self, csi):
""" Process the clear screen escape sequence. """
# default to 0
if len(csi['vals']) == 0:
csi['val'] = 0
@ -666,24 +827,24 @@ class Conque:
# clear coloration
if csi['val'] == 2 or csi['val'] == 0:
real_line = self.screen.get_real_line(self.l)
buffer_line = self.get_buffer_line(self.l)
for line in self.color_history.keys():
if line >= real_line:
if line >= buffer_line:
for syn in self.color_history[line]:
vim.command('syn clear ' + syn['name'])
self.color_changes = {}
# }}}
def csi_delete_chars(self, csi): # {{{
def csi_delete_chars(self, csi):
self.screen[self.l] = self.screen[self.l][:self.c] + self.screen[self.l][self.c + csi['val']:]
# }}}
def csi_add_spaces(self, csi): # {{{
def csi_add_spaces(self, csi):
self.screen[self.l] = self.screen[self.l][: self.c - 1] + ' ' * csi['val'] + self.screen[self.l][self.c:]
# }}}
def csi_cursor(self, csi): # {{{
def csi_cursor(self, csi):
if len(csi['vals']) == 2:
new_line = csi['vals'][0]
new_col = csi['vals'][1]
@ -700,9 +861,9 @@ class Conque:
if self.c > len(self.screen[self.l]):
self.screen[self.l] = self.screen[self.l] + ' ' * (self.c - len(self.screen[self.l]))
# }}}
def csi_set_coords(self, csi): # {{{
def csi_set_coords(self, csi):
if len(csi['vals']) == 2:
new_start = csi['vals'][0]
new_end = csi['vals'][1]
@ -721,9 +882,9 @@ class Conque:
self.l = self.bottom
self.color_changes = {}
# }}}
def csi_tab_clear(self, csi): # {{{
def csi_tab_clear(self, csi):
# this escape defaults to 0
if len(csi['vals']) == 0:
csi['val'] = 0
@ -735,9 +896,9 @@ class Conque:
elif csi['val'] == 3:
for i in range(0, self.columns + 1):
self.tabstops[i] = False
# }}}
def csi_set(self, csi): # {{{
def csi_set(self, csi):
# 132 cols
if csi['val'] == 3:
self.csi_clear_screen(self.parse_csi('2J'))
@ -753,9 +914,9 @@ class Conque:
self.color_changes = {}
# }}}
def csi_reset(self, csi): # {{{
def csi_reset(self, csi):
# 80 cols
if csi['val'] == 3:
self.csi_clear_screen(self.parse_csi('2J'))
@ -771,31 +932,31 @@ class Conque:
self.color_changes = {}
# }}}
# }}}
###############################################################################################
# ESC functions {{{
# ESC functions
def esc_scroll_up(self): # {{{
def esc_scroll_up(self):
self.ctl_nl()
self.color_changes = {}
# }}}
def esc_next_line(self): # {{{
def esc_next_line(self):
self.ctl_nl()
self.c = 1
# }}}
def esc_set_tab(self): # {{{
def esc_set_tab(self):
if self.c <= len(self.tabstops):
self.tabstops[self.c - 1] = True
# }}}
def esc_scroll_down(self): # {{{
def esc_scroll_down(self):
if self.l == self.top:
del self.screen[self.bottom]
self.screen.insert(self.top, '')
@ -803,24 +964,23 @@ class Conque:
self.l += -1
self.color_changes = {}
# }}}
# }}}
###############################################################################################
# HASH functions {{{
# HASH functions
def hash_screen_alignment_test(self): # {{{
def hash_screen_alignment_test(self):
self.csi_clear_screen(self.parse_csi('2J'))
self.working_lines = self.lines
for l in range(1, self.lines + 1):
self.screen[l] = 'E' * self.working_columns
# }}}
# }}}
###############################################################################################
# CHARSET functions {{{
# CHARSET functions
def charset_us(self):
self.character_set = 'ascii'
@ -831,15 +991,22 @@ class Conque:
def charset_graphics(self):
self.character_set = 'graphics'
# }}}
###############################################################################################
# Random stuff {{{
# Random stuff
def set_cursor(self, line, col):
""" Set cursor position in the Vim buffer.
Note: the line and column numbers are relative to the top left corner of the
visible screen. Not the line number in the Vim buffer.
"""
self.screen.set_cursor(line, col)
def change_title(self, key, val):
""" Change the Vim window title. """
if key == '0' or key == '2':
@ -850,17 +1017,14 @@ class Conque:
except:
pass
def paste(self):
input = vim.eval('@@')
input = input.replace("\n", "\r")
self.read(50)
def paste_selection(self):
input = vim.eval('@@')
input = input.replace("\n", "\r")
self.write(input)
def update_window_size(self, force=False):
""" Check and save the current buffer dimensions.
If the buffer size has changed, the update_window_size() method both updates
the Conque buffer size attributes as well as sending the new dimensions to the
subprocess pty.
"""
# resize if needed
if force or vim.current.window.width != self.columns or vim.current.window.height != self.lines:
@ -883,6 +1047,7 @@ class Conque:
self.proc.window_resize(self.lines, self.columns)
def insert_enter(self):
""" Run commands when user enters insert mode. """
# check window size
self.update_window_size()
@ -891,6 +1056,7 @@ class Conque:
self.cursor_set = False
def init_tabstops(self):
""" Intitialize terminal tabstop positions. """
for i in range(0, self.columns + 1):
if i % 8 == 0:
self.tabstops.append(True)
@ -898,23 +1064,30 @@ class Conque:
self.tabstops.append(False)
def idle(self):
""" Called when this terminal becomes idle. """
pass
def resume(self):
""" Called when this terminal is no longer idle. """
pass
pass
def close(self):
""" End the process running in the terminal. """
self.proc.close()
def abort(self):
""" Forcefully end the process running in the terminal. """
self.proc.signal(1)
# }}}
###############################################################################################
# Utility {{{
# Utility
def parse_csi(self, s):
""" Parse an escape sequence into it's meaningful values. """
def parse_csi(self, s): # {{{
attr = {'key': s[-1], 'flag': '', 'val': 1, 'vals': []}
if len(s) == 1:
@ -939,9 +1112,10 @@ class Conque:
attr['val'] = int(attr['vals'][0])
return attr
# }}}
def bound(self, val, min, max): # {{{
def bound(self, val, min, max):
""" TODO: This probably exists as a builtin function. """
if val > max:
return max
@ -949,9 +1123,10 @@ class Conque:
return min
return val
# }}}
def xterm_to_rgb(self, color_code): # {{{
def xterm_to_rgb(self, color_code):
""" Translate a terminal color number into a RGB string. """
if color_code < 16:
ascii_colors = ['000000', 'CD0000', '00CD00', 'CDCD00', '0000EE', 'CD00CD', '00CDCD', 'E5E5E5',
'7F7F7F', 'FF0000', '00FF00', 'FFFF00', '5C5CFF', 'FF00FF', '00FFFF', 'FFFFFF']
@ -968,8 +1143,12 @@ class Conque:
else:
grey_tone = "%02x" % math.floor((255 / 24) * (color_code - 232))
return grey_tone + grey_tone + grey_tone
# }}}
# }}}
# vim:foldmethod=marker
def get_buffer_line(self, line):
""" Get the buffer line number corresponding to the supplied screen line number. """
return self.screen.get_buffer_line(line)

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_globals.py {{{
# FILE: autoload/conque_term/conque_globals.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,56 +25,32 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""Common global constants and functions for Conque."""
import sys
import os
import re
import os # DEBUG
# shared memory size
CONQUE_SOLE_BUFFER_LENGTH = 1000
CONQUE_SOLE_INPUT_SIZE = 1000
CONQUE_SOLE_STATS_SIZE = 1000
CONQUE_SOLE_COMMANDS_SIZE = 255
CONQUE_SOLE_RESCROLL_SIZE = 255
CONQUE_SOLE_RESIZE_SIZE = 255
# interval of screen redraw
# larger number means less frequent
CONQUE_SOLE_SCREEN_REDRAW = 100
# interval of full buffer redraw
# larger number means less frequent
CONQUE_SOLE_BUFFER_REDRAW = 500
# interval of full output bucket replacement
# larger number means less frequent, 1 = every time
CONQUE_SOLE_MEM_REDRAW = 1000
import traceback # DEBUG
# PYTHON VERSION
CONQUE_PYTHON_VERSION = sys.version_info[0]
# Encoding
def u(str_val, str_encoding='latin-1', errors='strict'):
"""foolhardy attempt to make unicode string syntax compatible with both python 2 and 3"""
try:
# Vim's character encoding
import vim
CONQUE_VIM_ENCODING = vim.eval('&encoding')
except:
CONQUE_VIM_ENCODING = 'utf-8'
def u(str_val, str_encoding='utf-8', errors='strict'):
""" Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """
if not str_val:
str_val = ''
@ -85,7 +61,34 @@ def u(str_val, str_encoding='latin-1', errors='strict'):
else:
return unicode(str_val, str_encoding, errors)
# Escape sequence settings {{{
def uchr(str):
""" Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """
if CONQUE_PYTHON_VERSION == 3:
return chr(str)
else:
return unichr(str)
# Unix escape sequence settings
CONQUE_CTL = {
1: 'soh', # start of heading
@ -209,7 +212,7 @@ CONQUE_GRAPHICS_SET = [
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
]
# Font codes {{{
# Font codes
CONQUE_FONT = {
0: {'description': 'Normal (default)', 'attributes': {'cterm': 'NONE', 'ctermfg': 'NONE', 'ctermbg': 'NONE', 'gui': 'NONE', 'guifg': 'NONE', 'guibg': 'NONE'}, 'normal': True},
1: {'description': 'Bold', 'attributes': {'cterm': 'BOLD', 'gui': 'BOLD'}, 'normal': False},
@ -257,31 +260,60 @@ CONQUE_FONT = {
106: {'description': 'Set background color to Cyan', 'attributes': {'ctermbg': '14', 'guibg': '#009999'}, 'normal': False},
107: {'description': 'Set background color to White', 'attributes': {'ctermbg': '15', 'guibg': '#ffffff'}, 'normal': False}
}
# }}}
# regular expression matching (almost) all control sequences
CONQUE_SEQ_REGEX = re.compile(u("(\x1b\[?\??#?[0-9;]*[a-zA-Z0-9@=>]|\x1b\][0-9];.*?\x07|[\x01-\x0f]|\x1b\([AB0])"), re.UNICODE)
CONQUE_SEQ_REGEX_CTL = re.compile(u("^[\x01-\x0f]$"), re.UNICODE)
CONQUE_SEQ_REGEX_CSI = re.compile(u("^\x1b\["), re.UNICODE)
CONQUE_SEQ_REGEX_TITLE = re.compile(u("^\x1b\]"), re.UNICODE)
CONQUE_SEQ_REGEX_HASH = re.compile(u("^\x1b#"), re.UNICODE)
CONQUE_SEQ_REGEX_ESC = re.compile(u("^\x1b.$"), re.UNICODE)
CONQUE_SEQ_REGEX_CHAR = re.compile(u("^\x1b\("), re.UNICODE)
CONQUE_SEQ_REGEX = re.compile("(\x1b\[?\??#?[0-9;]*[a-zA-Z0-9@=>]|\x1b\][0-9];.*?\x07|[\x01-\x0f]|\x1b\([AB0])")
CONQUE_SEQ_REGEX_CTL = re.compile("^[\x01-\x0f]$")
CONQUE_SEQ_REGEX_CSI = re.compile("^\x1b\[")
CONQUE_SEQ_REGEX_TITLE = re.compile("^\x1b\]")
CONQUE_SEQ_REGEX_HASH = re.compile("^\x1b#")
CONQUE_SEQ_REGEX_ESC = re.compile("^\x1b.$")
CONQUE_SEQ_REGEX_CHAR = re.compile("^\x1b[()]")
# match table output
CONQUE_TABLE_OUTPUT = re.compile("^\s*\|\s.*\s\|\s*$|^\s*\+[=+-]+\+\s*$")
# }}}
# Windows subprocess config {{{
CONQUE_SEQ_REGEX_VK = re.compile(u("(\x1b\[\d{1,3}VK)"), re.UNICODE)
# }}}
# basic terminal colors
CONQUE_COLOR_SEQUENCE = (
'000', '009', '090', '099', '900', '909', '990', '999',
'000', '00f', '0f0', '0ff', 'f00', 'f0f', 'ff0', 'fff'
)
# vim:foldmethod=marker
# Windows subprocess constants
# shared memory size
CONQUE_SOLE_BUFFER_LENGTH = 1000
CONQUE_SOLE_INPUT_SIZE = 1000
CONQUE_SOLE_STATS_SIZE = 1000
CONQUE_SOLE_COMMANDS_SIZE = 255
CONQUE_SOLE_RESCROLL_SIZE = 255
CONQUE_SOLE_RESIZE_SIZE = 255
# interval of screen redraw
# larger number means less frequent
CONQUE_SOLE_SCREEN_REDRAW = 50
# interval of full buffer redraw
# larger number means less frequent
CONQUE_SOLE_BUFFER_REDRAW = 500
# interval of full output bucket replacement
# larger number means less frequent, 1 = every time
CONQUE_SOLE_MEM_REDRAW = 1000
# maximum number of lines with terminal colors
# ignored if g:ConqueTerm_Color = 2
CONQUE_MAX_SYNTAX_LINES = 200
# windows input splitting on special keys
CONQUE_WIN32_REGEX_VK = re.compile("(\x1b\[[0-9;]+VK)")
# windows attribute string splitting
CONQUE_WIN32_REGEX_ATTR = re.compile("((.)\\2*)", re.DOTALL)
# special key attributes
CONQUE_VK_ATTR_CTRL_PRESSED = u('1024')

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_screen.py {{{
# FILE: autoload/conque_term/conque_screen.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,14 +25,19 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""
ConqueScreen is an extention of the vim.current.buffer object
It restricts the working indices of the buffer object to the scroll region
which pty is expecting. It also uses 1-based indexes, to match escape
sequence commands.
Unix terminal escape sequences usually reference line numbers relative to the
top of the visible screen. However the visible portion of the Vim buffer
representing the terminal probably doesn't start at the first line of the
buffer.
The ConqueScreen class allows access to the Vim buffer with screen-relative
line numbering. And handles a few other related tasks, such as setting the
correct cursor position.
E.g.:
s = ConqueScreen()
@ -40,6 +45,7 @@ sequence commands.
s[5] = 'Set 5th line in terminal to this line'
s.append('Add new line to terminal')
s[5] = 'Since previous append() command scrolled the terminal down, this is a different line than first cb[5] call'
"""
import vim
@ -47,8 +53,6 @@ import vim
class ConqueScreen(object):
# CLASS PROPERTIES {{{
# the buffer
buffer = None
@ -59,55 +63,66 @@ class ConqueScreen(object):
screen_width = 80
screen_height = 80
# }}}
# char encoding for vim buffer
screen_encoding = 'utf-8'
def __init__(self):
""" Initialize screen size and character encoding. """
def __init__(self): # {{{
self.buffer = vim.current.buffer
# initialize screen size
self.screen_top = 1
self.screen_width = vim.current.window.width
self.screen_height = vim.current.window.height
# }}}
###############################################################################################
# List overload {{{
# save screen character encoding type
self.screen_encoding = vim.eval('&fileencoding')
def __len__(self): # {{{
def __len__(self):
""" Define the len() function for ConqueScreen objects. """
return len(self.buffer)
# }}}
def __getitem__(self, key): # {{{
real_line = self.get_real_idx(key)
def __getitem__(self, key):
""" Define value access for ConqueScreen objects. """
buffer_line = self.get_real_idx(key)
# if line is past buffer end, add lines to buffer
if real_line >= len(self.buffer):
for i in range(len(self.buffer), real_line + 1):
self.append(' ' * self.screen_width)
if buffer_line >= len(self.buffer):
for i in range(len(self.buffer), buffer_line + 1):
self.append(' ')
return u(self.buffer[real_line], 'utf-8')
# }}}
return u(self.buffer[buffer_line], 'utf-8')
def __setitem__(self, key, value): # {{{
real_line = self.get_real_idx(key)
def __setitem__(self, key, value):
""" Define value assignments for ConqueScreen objects. """
buffer_line = self.get_real_idx(key)
if CONQUE_PYTHON_VERSION == 2:
val = value.encode('utf-8')
val = value.encode(self.screen_encoding)
else:
# XXX / Vim's python3 interface doesn't accept bytes object
val = str(value)
# if line is past end of screen, append
if real_line == len(self.buffer):
if buffer_line == len(self.buffer):
self.buffer.append(val)
else:
self.buffer[real_line] = val
# }}}
self.buffer[buffer_line] = val
def __delitem__(self, key): # {{{
def __delitem__(self, key):
""" Define value deletion for ConqueScreen objects. """
del self.buffer[self.screen_top + key - 2]
# }}}
def append(self, value): # {{{
def append(self, value):
""" Define value appending for ConqueScreen objects. """
if len(self.buffer) > self.screen_top + self.screen_height - 1:
self.buffer[len(self.buffer) - 1] = value
else:
@ -115,72 +130,83 @@ class ConqueScreen(object):
if len(self.buffer) > self.screen_top + self.screen_height - 1:
self.screen_top += 1
if vim.current.buffer.number == self.buffer.number:
vim.command('normal G')
# }}}
def insert(self, line, value): # {{{
if vim.current.buffer.number == self.buffer.number:
vim.command('normal! G')
def insert(self, line, value):
""" Define value insertion for ConqueScreen objects. """
l = self.screen_top + line - 2
self.buffer.append(value, l)
# }}}
# }}}
###############################################################################################
# Util {{{
def get_top(self): # {{{
def get_top(self):
""" Get the Vim line number representing the top of the visible terminal. """
return self.screen_top
# }}}
def get_real_idx(self, line): # {{{
def get_real_idx(self, line):
""" Get the zero index Vim line number corresponding to the provided screen line. """
return (self.screen_top + line - 2)
# }}}
def get_real_line(self, line): # {{{
def get_buffer_line(self, line):
""" Get the Vim line number corresponding to the provided screen line. """
return (self.screen_top + line - 1)
# }}}
def set_screen_width(self, width): # {{{
def set_screen_width(self, width):
""" Set the screen width. """
self.screen_width = width
# }}}
# }}}
###############################################################################################
def clear(self): # {{{
def clear(self):
""" Clear the screen. Does not clear the buffer, just scrolls down past all text. """
self.screen_width = width
self.buffer.append(' ')
vim.command('normal Gzt')
vim.command('normal! Gzt')
self.screen_top = len(self.buffer)
# }}}
def set_cursor(self, line, column): # {{{
def set_cursor(self, line, column):
""" Set cursor position. """
# figure out line
real_line = self.screen_top + line - 1
if real_line > len(self.buffer):
for l in range(len(self.buffer) - 1, real_line):
buffer_line = self.screen_top + line - 1
if buffer_line > len(self.buffer):
for l in range(len(self.buffer) - 1, buffer_line):
self.buffer.append('')
# figure out column
real_column = column
if len(self.buffer[real_line - 1]) < real_column:
self.buffer[real_line - 1] = self.buffer[real_line - 1] + ' ' * (real_column - len(self.buffer[real_line - 1]))
if len(self.buffer[buffer_line - 1]) < real_column:
self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1]))
# python version is occasionally grumpy
try:
vim.current.window.cursor = (real_line, real_column - 1)
except:
vim.command('call cursor(' + str(real_line) + ', ' + str(real_column) + ')')
# }}}
if not CONQUE_FAST_MODE:
# set cursor at byte index of real_column'th character
vim.command('call cursor(' + str(buffer_line) + ', byteidx(getline(' + str(buffer_line) + '), ' + str(real_column) + '))')
else:
# old version
# python version is occasionally grumpy
try:
vim.current.window.cursor = (buffer_line, real_column - 1)
except:
vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')')
def reset_size(self, line):
""" Change screen size """
def reset_size(self, line): # {{{
# save cursor line number
real_line = self.screen_top + line
buffer_line = self.screen_top + line
# reset screen size
self.screen_width = vim.current.window.width
@ -191,19 +217,14 @@ class ConqueScreen(object):
# align bottom of buffer to bottom of screen
vim.command('normal ' + str(self.screen_height) + 'kG')
vim.command('normal! ' + str(self.screen_height) + 'kG')
# return new relative line number
return (real_line - self.screen_top)
# }}}
return (buffer_line - self.screen_top)
def scroll_to_bottom(self): # {{{
vim.current.window.cursor = (len(self.buffer) - 1, 1)
# }}}
def align(self): # {{{
# align bottom of buffer to bottom of screen
vim.command('normal ' + str(self.screen_height) + 'kG')
# }}}
def align(self):
""" align bottom of buffer to bottom of screen """
vim.command('normal! ' + str(self.screen_height) + 'kG')
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole.py {{{
# FILE: autoload/conque_term/conque_sole.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,7 +25,14 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""
Windows Console Emulator
This is the main interface to the Windows emulator. It reads new output from the background console
and updates the Vim buffer.
"""
import vim
@ -36,19 +43,36 @@ class ConqueSole(Conque):
window_bottom = None
color_cache = {}
attribute_cache = {}
color_mode = None
color_conceals = {}
buffer = None
encoding = None
# counters for periodic rendering
buffer_redraw_ct = 0
screen_redraw_ct = 0
buffer_redraw_ct = 1
screen_redraw_ct = 1
# *********************************************************************************************
# start program and initialize this instance
# line offset, shifts output down
offset = 0
def open(self, command, options={}, python_exe='', communicator_py=''): # {{{
def open(self):
""" Start command and initialize this instance
Arguments:
command - Command string, e.g. "Powershell.exe"
options - Dictionary of config options
python_exe - Path to the python.exe executable. Usually C:\PythonXX\python.exe
communicator_py - Path to subprocess controller script in user's vimfiles directory
"""
# get arguments
command = vim.eval('command')
options = vim.eval('options')
python_exe = vim.eval('py_exe')
communicator_py = vim.eval('py_vim')
# init size
self.columns = vim.current.window.width
@ -56,22 +80,25 @@ class ConqueSole(Conque):
self.window_top = 0
self.window_bottom = vim.current.window.height - 1
# color mode
self.color_mode = vim.eval('g:ConqueTerm_ColorMode')
# line offset
self.offset = int(options['offset'])
# init color
self.enable_colors = options['color']
self.enable_colors = options['color'] and not CONQUE_FAST_MODE
# open command
self.proc = ConqueSoleWrapper()
self.proc.open(command, {'TERM': options['TERM'], 'CONQUE': '1', 'LINES': self.lines, 'COLUMNS': self.columns}, python_exe, communicator_py)
self.proc.open(command, self.lines, self.columns, python_exe, communicator_py, options)
self.buffer = vim.current.buffer
# }}}
self.screen_encoding = vim.eval('&fileencoding')
# *********************************************************************************************
# read and update screen
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): # {{{
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True):
""" Read from console and update Vim buffer. """
try:
stats = self.proc.get_stats()
@ -79,48 +106,59 @@ class ConqueSole(Conque):
if not stats:
return
self.buffer_redraw_ct += 1
self.screen_redraw_ct += 1
# disable screen and buffer redraws in fast mode
if not CONQUE_FAST_MODE:
self.buffer_redraw_ct += 1
self.screen_redraw_ct += 1
update_top = 0
update_bottom = 0
lines = []
# full buffer redraw, our favorite!
if self.buffer_redraw_ct == CONQUE_SOLE_BUFFER_REDRAW:
self.buffer_redraw_ct = 0
update_top = 0
update_bottom = stats['top_offset'] + self.lines
(lines, attributes) = self.proc.read(update_top, update_bottom)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
for i in range(update_top, update_bottom + 1):
self.plain_text(i, lines[i], attributes[i], stats)
#if self.buffer_redraw_ct == CONQUE_SOLE_BUFFER_REDRAW:
# self.buffer_redraw_ct = 0
# update_top = 0
# update_bottom = stats['top_offset'] + self.lines
# (lines, attributes) = self.proc.read(update_top, update_bottom)
# if return_output:
# output = self.get_new_output(lines, update_top, stats)
# if update_buffer:
# for i in range(update_top, update_bottom + 1):
# if CONQUE_FAST_MODE:
# self.plain_text(i, lines[i], None, stats)
# else:
# self.plain_text(i, lines[i], attributes[i], stats)
# full screen redraw
elif stats['cursor_y'] + 1 != self.l or stats['top_offset'] != self.window_top or self.screen_redraw_ct == CONQUE_SOLE_SCREEN_REDRAW:
if stats['cursor_y'] + 1 != self.l or stats['top_offset'] != self.window_top or self.screen_redraw_ct >= CONQUE_SOLE_SCREEN_REDRAW:
self.screen_redraw_ct = 0
update_top = self.window_top
update_bottom = stats['top_offset'] + self.lines + 1
update_bottom = max([stats['top_offset'] + self.lines + 1, stats['cursor_y']])
(lines, attributes) = self.proc.read(update_top, update_bottom - update_top + 1)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
for i in range(update_top, update_bottom + 1):
self.plain_text(i, lines[i - update_top], attributes[i - update_top], stats)
if CONQUE_FAST_MODE:
self.plain_text(i, lines[i - update_top], None, stats)
else:
self.plain_text(i, lines[i - update_top], attributes[i - update_top], stats)
# single line redraw
else:
update_top = stats['cursor_y']
update_bottom = stats['cursor_y']
(lines, attributes) = self.proc.read(update_top, 1)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
if lines[0].rstrip() != self.buffer[update_top].rstrip():
self.plain_text(update_top, lines[0], attributes[0], stats)
if lines[0].rstrip() != u(self.buffer[update_top].rstrip()):
if CONQUE_FAST_MODE:
self.plain_text(update_top, lines[0], None, stats)
else:
self.plain_text(update_top, lines[0], attributes[0], stats)
# reset current position
@ -138,12 +176,10 @@ class ConqueSole(Conque):
except:
pass
# }}}
#########################################################################
# Calculate the "new" output from this read. Fake but useful
def get_new_output(self, lines, update_top, stats): # {{{
def get_new_output(self, lines, update_top, stats):
""" Calculate the "new" output from this read. Fake but useful """
if not (stats['cursor_y'] + 1 > self.l or (stats['cursor_y'] + 1 == self.l and stats['cursor_x'] + 1 > self.c)):
return ""
@ -175,18 +211,19 @@ class ConqueSole(Conque):
return "\n".join(new_output)
# }}}
#########################################################################
# update the buffer
def plain_text(self, line_nr, text, attributes, stats): # {{{
def plain_text(self, line_nr, text, attributes, stats):
""" Write plain text to Vim buffer. """
self.l = line_nr + 1
# handle line offset
line_nr += self.offset
self.l = line_nr + 1
# remove trailing whitespace
text = text.rstrip()
@ -197,21 +234,28 @@ class ConqueSole(Conque):
text = self.add_conceal_color(text, attributes, stats, line_nr)
# deal with character encoding
if CONQUE_PYTHON_VERSION == 2:
val = text.encode(self.screen_encoding)
else:
# XXX / Vim's python3 interface doesn't accept bytes object
val = str(text)
# update vim buffer
if len(self.buffer) <= line_nr:
self.buffer.append(text)
self.buffer.append(val)
else:
self.buffer[line_nr] = text
self.buffer[line_nr] = val
if not self.color_mode == 'conceal':
self.do_color(attributes=attributes, stats=stats)
if self.enable_colors and not self.color_mode == 'conceal' and line_nr > self.l - CONQUE_MAX_SYNTAX_LINES:
relevant = attributes[0:len(text)]
if line_nr not in self.attribute_cache or self.attribute_cache[line_nr] != relevant:
self.do_color(attributes=relevant, stats=stats)
self.attribute_cache[line_nr] = relevant
# }}}
#########################################################################
# add conceal color
def add_conceal_color(self, text, attributes, stats, line_nr): # {{{
def add_conceal_color(self, text, attributes, stats, line_nr):
""" Add 'conceal' color strings to output text """
# stop here if coloration is disabled
if not self.enable_colors:
@ -222,71 +266,42 @@ class ConqueSole(Conque):
return text
new_text = ''
# if text attribute is different, call add_color()
attr = None
start = 0
self.color_conceals[line_nr] = []
attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes)
offset = 0
ends = []
for i in range(0, len(attributes)):
c = ord(attributes[i])
for attr in attribute_chunks:
attr_num = ord(attr[1])
ends = []
if attr_num != stats['default_attribute']:
if c != attr:
if attr and attr != stats['default_attribute']:
color = self.translate_color(attr_num)
color = self.translate_color(attr)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
self.color_conceals[line_nr].append(offset)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
self.color_conceals[line_nr].append(start)
if attr_num > 15:
new_text += chr(27) + 'sb' + color['bg_code'] + ';'
ends.append(chr(27) + 'eb' + color['bg_code'] + ';')
self.color_conceals[line_nr].append(offset)
if c > 15:
new_text += chr(27) + 'sf' + color['bg_code'] + ';'
ends.append(chr(27) + 'ef' + color['bg_code'] + ';')
self.color_conceals[line_nr].append(start)
new_text += text[offset:offset + len(attr[0])]
new_text += text[start:i]
# close color regions
ends.reverse()
for i in range(0, len(ends)):
self.color_conceals[line_nr].append(len(new_text))
new_text += ends[i]
# close color regions
ends.reverse()
for j in range(0, len(ends)):
new_text += ends[j]
self.color_conceals[line_nr].append(i)
ends = []
start = i
attr = c
if attr and attr != stats['default_attribute']:
color = self.translate_color(attr)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
if c > 15:
new_text += chr(27) + 'sf' + color['bg_code'] + ';'
ends.append(chr(27) + 'ef' + color['bg_code'] + ';')
new_text += text[start:]
# close color regions
ends.reverse()
for i in range(0, len(ends)):
new_text += ends[i]
offset += len(attr[0])
return new_text
# }}}
#########################################################################
def do_color(self, start=0, end=0, attributes='', stats=None): # {{{
# stop here if coloration is disabled
if not self.enable_colors:
return
def do_color(self, start=0, end=0, attributes='', stats=None):
""" Convert Windows console attributes into Vim syntax highlighting """
# if no colors for this line, clear everything out
if len(attributes) == 0 or attributes == u(chr(stats['default_attribute'])) * len(attributes):
@ -294,29 +309,18 @@ class ConqueSole(Conque):
self.apply_color(1, len(attributes), self.l)
return
# if text attribute is different, call add_color()
attr = None
start = 0
for i in range(0, len(attributes)):
c = ord(attributes[i])
if c != attr:
if attr and attr != stats['default_attribute']:
self.color_changes = self.translate_color(attr)
self.apply_color(start + 1, i + 1, self.l)
start = i
attr = c
if attr and attr != stats['default_attribute']:
self.color_changes = self.translate_color(attr)
self.apply_color(start + 1, len(attributes), self.l)
attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes)
offset = 0
for attr in attribute_chunks:
attr_num = ord(attr[1])
if attr_num != stats['default_attribute']:
self.color_changes = self.translate_color(attr_num)
self.apply_color(offset + 1, offset + len(attr[0]) + 1, self.l)
offset += len(attr[0])
# }}}
#########################################################################
def translate_color(self, attr): # {{{
def translate_color(self, attr):
""" Convert Windows console attributes into RGB colors """
# check for cached color
if attr in self.color_cache:
@ -363,24 +367,20 @@ class ConqueSole(Conque):
return color
# }}}
#########################################################################
# write virtual key code to shared memory using proprietary escape seq
def write_vk(self, vk_code): # {{{
def write_vk(self, vk_code):
""" write virtual key code to shared memory using proprietary escape seq """
self.proc.write_vk(vk_code)
# }}}
# *********************************************************************************************
# resize if needed
def update_window_size(self): # {{{
def update_window_size(self):
""" Resize underlying console if Vim buffer size has changed """
if vim.current.window.width != self.columns or vim.current.window.height != self.lines:
# reset all window size attributes to default
self.columns = vim.current.window.width
self.lines = vim.current.window.height
@ -390,12 +390,14 @@ class ConqueSole(Conque):
self.proc.window_resize(vim.current.window.height, vim.current.window.width)
# }}}
# *********************************************************************************************
# resize if needed
def set_cursor(self, line, column):
""" Update cursor position in Vim buffer """
def set_cursor(self, line, column): # {{{
# handle offset
line += self.offset
# shift cursor position to handle concealed text
if self.enable_colors and self.color_mode == 'conceal':
@ -406,54 +408,51 @@ class ConqueSole(Conque):
else:
break
# figure out line
real_line = line
if real_line > len(self.buffer):
for l in range(len(self.buffer) - 1, real_line):
buffer_line = line
if buffer_line > len(self.buffer):
for l in range(len(self.buffer) - 1, buffer_line):
self.buffer.append('')
# figure out column
real_column = column
if len(self.buffer[real_line - 1]) < real_column:
self.buffer[real_line - 1] = self.buffer[real_line - 1] + ' ' * (real_column - len(self.buffer[real_line - 1]))
if len(self.buffer[buffer_line - 1]) < real_column:
self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1]))
# python version is occasionally grumpy
try:
vim.current.window.cursor = (real_line, real_column - 1)
vim.current.window.cursor = (buffer_line, real_column - 1)
except:
vim.command('call cursor(' + str(real_line) + ', ' + str(real_column) + ')')
# }}}
vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')')
# *********************************************************************************************
# go into idle mode
def idle(self): # {{{
def idle(self):
""" go into idle mode """
self.proc.idle()
# }}}
# *********************************************************************************************
# resume from idle mode
def resume(self): # {{{
def resume(self):
""" resume from idle mode """
self.proc.resume()
# }}}
# *********************************************************************************************
# end subprocess
def close(self):
""" end console subprocess """
self.proc.close()
# *********************************************************************************************
# end subprocess forcefully
def abort(self):
""" end subprocess forcefully """
self.proc.close()
def get_buffer_line(self, line):
""" get buffer line """
return line
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_communicator.py {{{
# FILE: autoload/conque_term/conque_sole_communicator.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,17 +25,20 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""
ConqueSoleCommunicator
Script to transfer communications between python being run in Vim and a
subprocess run inside a Windows console. This is required since interactive
programs in Windows appear to require a console, and python run in Vim is
not attached to any console. So a console version of python must be initiated
for the subprocess. Communication is then done with the use of shared memory
objects. Good times!
This script will create a new Windows console and start the requested program
inside of it. This process is launched independently from the parent Vim
program, so it has no access to the vim module.
The main loop in this script reads data from the console and syncs it onto
blocks of memory shared with the Vim process. In this way the Vim process
and this script can communicate with each other.
"""
import time
@ -54,17 +57,12 @@ if __name__ == '__main__':
# attempt to catch ALL exceptions to fend of zombies
try:
# startup and config {{{
# simple arg validation
if len(sys.argv) < 5:
exit()
# shared memory size
CONQUE_SOLE_COMMANDS_SIZE = 255
# maximum time this thing reads. 0 means no limit. Only for testing.
max_loops = 0
@ -86,12 +84,18 @@ if __name__ == '__main__':
# console height
console_height = int(sys.argv[3])
# code page
code_page = int(sys.argv[4])
# code page
fast_mode = int(sys.argv[5])
# the actual subprocess to run
cmd_line = " ".join(sys.argv[4:])
cmd_line = " ".join(sys.argv[6:])
# width and height
options = {'LINES': console_height, 'COLUMNS': console_width}
options = {'LINES': console_height, 'COLUMNS': console_width, 'CODE_PAGE': code_page, 'FAST_MODE': fast_mode}
@ -106,12 +110,10 @@ if __name__ == '__main__':
is_idle = True
shm_command.clear()
# }}}
##############################################################
# Create the subprocess
# {{{
proc = ConqueSoleSubprocess()
res = proc.open(cmd_line, mem_key, options)
@ -119,8 +121,6 @@ if __name__ == '__main__':
exit()
# }}}
##############################################################
# main loop!
@ -135,7 +135,7 @@ if __name__ == '__main__':
if not proc.is_alive():
proc.close()
exit()
break
# check for change in buffer focus
cmd = shm_command.read()

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_shared_memory.py {{{
# FILE: autoload/conque_term/conque_sole_shared_memory.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,17 +25,20 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""Wrapper class for shared memory between Windows python processes"""
"""
Wrapper class for shared memory between Windows python processes
Adds a small amount of functionality to the standard mmap module.
"""
import mmap
import sys
if sys.version_info[0] == 2:
CONQUE_PYTHON_VERSION = 2
else:
CONQUE_PYTHON_VERSION = 3
# PYTHON VERSION
CONQUE_PYTHON_VERSION = sys.version_info[0]
if CONQUE_PYTHON_VERSION == 2:
import cPickle as pickle
@ -45,16 +48,14 @@ else:
class ConqueSoleSharedMemory():
# ****************************************************************************
# class properties
# {{{
# is the data being stored not fixed length
fixed_length = False
# maximum number of bytes per character, for fixed width blocks
char_width = 1
# fill memory with this character when clearing and fixed_length is true
fill_char = ' '
FILL_CHAR = None
# serialize and unserialize data automatically
serialize = False
@ -72,18 +73,25 @@ class ConqueSoleSharedMemory():
shm = None
# character encoding, dammit
encoding = 'ascii'
encoding = 'utf-8'
# pickle terminator
TERMINATOR = None
# }}}
# ****************************************************************************
# constructor I guess
def __init__(self, mem_size, mem_type, mem_key, fixed_length=False, fill_char=' ', serialize=False, encoding='utf-8'):
""" Initialize new shared memory block instance
def __init__(self, mem_size, mem_type, mem_key, fixed_length=False, fill_char=' ', serialize=False, encoding='ascii'): # {{{
Arguments:
mem_size -- Memory size in characters, depends on encoding argument to calcuate byte size
mem_type -- Label to identify what will be stored
mem_key -- Unique, probably random key to identify this block
fixed_length -- If set to true, assume the data stored will always fill the memory size
fill_char -- Initialize memory block with this character, only really helpful with fixed_length blocks
serialize -- Automatically serialize data passed to write. Allows storing non-byte data
encoding -- Character encoding to use when storing character data
"""
self.mem_size = mem_size
self.mem_type = mem_type
self.mem_key = mem_key
@ -93,12 +101,17 @@ class ConqueSoleSharedMemory():
self.encoding = encoding
self.TERMINATOR = str(chr(0)).encode(self.encoding)
# }}}
if CONQUE_PYTHON_VERSION == 3:
self.FILL_CHAR = fill_char
else:
self.FILL_CHAR = unicode(fill_char)
# ****************************************************************************
# create memory block
if fixed_length and encoding == 'utf-8':
self.char_width = 4
def create(self, access='write'): # {{{
def create(self, access='write'):
""" Create a new block of shared memory using the mmap module. """
if access == 'write':
mmap_access = mmap.ACCESS_WRITE
@ -107,28 +120,28 @@ class ConqueSoleSharedMemory():
name = "conque_%s_%s" % (self.mem_type, self.mem_key)
self.shm = mmap.mmap(0, self.mem_size, name, mmap_access)
self.shm = mmap.mmap(0, self.mem_size * self.char_width, name, mmap_access)
if not self.shm:
return False
else:
return True
# }}}
# ****************************************************************************
# read data
def read(self, chars=1, start=0):
""" Read data from shared memory.
def read(self, chars=1, start=0): # {{{
# invalid reads
if self.fixed_length and (chars == 0 or start + chars > self.mem_size):
return ''
If this is a fixed length block, read 'chars' characters from memory.
Otherwise read up until the TERMINATOR character (null byte).
If this memory is serialized, unserialize it automatically.
"""
# go to start position
self.shm.seek(start)
self.shm.seek(start * self.char_width)
if not self.fixed_length:
if self.fixed_length:
chars = chars * self.char_width
else:
chars = self.shm.find(self.TERMINATOR)
if chars == 0:
@ -150,13 +163,15 @@ class ConqueSoleSharedMemory():
return shm_str
# }}}
# ****************************************************************************
# write data
def write(self, text, start=0):
""" Write data to memory.
def write(self, text, start=0): # {{{
If memory is fixed length, simply write the 'text' characters at 'start' position.
Otherwise write 'text' characters and append a null character.
If memory is serializable, do so first.
"""
# simple scenario, let pickle create bytes
if self.serialize:
if CONQUE_PYTHON_VERSION == 3:
@ -167,36 +182,29 @@ class ConqueSoleSharedMemory():
else:
tb = text.encode(self.encoding, 'replace')
self.shm.seek(start)
# write to memory
self.shm.seek(start * self.char_width)
if self.fixed_length:
self.shm.write(tb)
else:
self.shm.write(tb + self.TERMINATOR)
# }}}
# ****************************************************************************
# clear
def clear(self, start=0): # {{{
def clear(self, start=0):
""" Clear memory block using self.fill_char. """
self.shm.seek(start)
if self.fixed_length:
self.shm.write(str(self.fill_char * self.mem_size).encode(self.encoding))
self.shm.write(str(self.fill_char * self.mem_size * self.char_width).encode(self.encoding))
else:
self.shm.write(self.TERMINATOR)
# }}}
# ****************************************************************************
# close
def close(self):
""" Close/destroy memory block. """
self.shm.close()
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_subprocess.py {{{
# FILE: autoload/conque_term/conque_sole_subprocess.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,9 +25,9 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
""" ConqueSoleSubprocess {{{
""" ConqueSoleSubprocess
Creates a new subprocess with it's own (hidden) console window.
@ -47,12 +47,7 @@ Sample Usage:
shm_in.write("dir\r")
output = shm_out.read(...)
Requirements:
* Python for Windows extensions. Available at http://sourceforge.net/projects/pywin32/
* Must be run from process attached to an existing console.
}}} """
"""
import time
import re
@ -66,9 +61,7 @@ from conque_sole_shared_memory import *
class ConqueSoleSubprocess():
# Class properties {{{
#window = None
# subprocess handle and pid
handle = None
pid = None
@ -117,25 +110,16 @@ class ConqueSoleSubprocess():
# are we still a valid process?
is_alive = True
# running in fast mode
fast_mode = 0
# used for periodic execution of screen and memory redrawing
screen_redraw_ct = 0
mem_redraw_ct = 0
# }}}
# ****************************************************************************
# initialize class instance
def __init__(self): # {{{
pass
# }}}
# ****************************************************************************
# Create proccess cmd
def open(self, cmd, mem_key, options={}): # {{{
def open(self, cmd, mem_key, options={}):
""" Create subproccess running in hidden console window. """
@ -156,6 +140,9 @@ class ConqueSoleSubprocess():
self.window_height = options['LINES']
self.buffer_width = options['COLUMNS']
# fast mode
self.fast_mode = options['FAST_MODE']
# console window options
si = STARTUPINFO()
@ -178,15 +165,18 @@ class ConqueSoleSubprocess():
# process info
self.pid = pi.dwProcessId
self.handle = pi.hProcess
# attach ourselves to the new console
# console is not immediately available
for i in range(10):
time.sleep(1)
time.sleep(0.25)
try:
res = ctypes.windll.kernel32.AttachConsole(self.pid)
@ -221,6 +211,13 @@ class ConqueSoleSubprocess():
# set window size
self.set_window_size(self.window_width, self.window_height)
# set utf-8 code page
if 'CODE_PAGE' in options and options['CODE_PAGE'] > 0:
if ctypes.windll.kernel32.IsValidCodePage(ctypes.c_uint(options['CODE_PAGE'])):
ctypes.windll.kernel32.SetConsoleCP(ctypes.c_uint(options['CODE_PAGE']))
ctypes.windll.kernel32.SetConsoleOutputCP(ctypes.c_uint(options['CODE_PAGE']))
# init shared memory
self.init_shared_memory(mem_key)
@ -234,17 +231,9 @@ class ConqueSoleSubprocess():
return False
# }}}
# ****************************************************************************
# create shared memory objects
def init_shared_memory(self, mem_key): # {{{
buf_info = self.get_buffer_info()
def init_shared_memory(self, mem_key):
""" Create shared memory objects. """
self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key)
self.shm_input.create('write')
@ -254,9 +243,11 @@ class ConqueSoleSubprocess():
self.shm_output.create('write')
self.shm_output.clear()
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
if not self.fast_mode:
buf_info = self.get_buffer_info()
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True)
self.shm_stats.create('write')
@ -276,12 +267,9 @@ class ConqueSoleSubprocess():
return True
# }}}
# ****************************************************************************
# check for and process commands
def check_commands(self): # {{{
def check_commands(self):
""" Check for and process commands from Vim. """
cmd = self.shm_command.read()
@ -320,12 +308,9 @@ class ConqueSoleSubprocess():
buf_info = self.get_buffer_info()
self.reset_console(buf_info, add_block=False)
# }}}
# ****************************************************************************
# read from windows console and update output buffer
def read(self, timeout=0): # {{{
def read(self):
""" Read from windows console and update shared memory blocks. """
# no point really
if self.screen_redraw_ct == 0 and not self.is_alive():
@ -337,12 +322,6 @@ class ConqueSoleSubprocess():
# check for commands
self.check_commands()
# emulate timeout by sleeping timeout time
if timeout > 0:
read_timeout = float(timeout) / 1000
time.sleep(read_timeout)
# get cursor position
buf_info = self.get_buffer_info()
curs_line = buf_info.dwCursorPosition.Y
@ -353,12 +332,15 @@ class ConqueSoleSubprocess():
self.screen_redraw_ct = 0
read_start = self.top
read_end = buf_info.srWindow.Bottom + 1
read_end = max([buf_info.srWindow.Bottom + 1, curs_line + 1])
else:
read_start = curs_line
read_end = curs_line + 1
# vars used in for loop
coord = COORD(0, 0)
chars_read = ctypes.c_int(0)
@ -369,45 +351,68 @@ class ConqueSoleSubprocess():
coord.Y = i
res = ctypes.windll.kernel32.ReadConsoleOutputCharacterW(self.stdout, ctypes.byref(self.tc), self.buffer_width, coord, ctypes.byref(chars_read))
ctypes.windll.kernel32.ReadConsoleOutputAttribute(self.stdout, ctypes.byref(self.ac), self.buffer_width, coord, ctypes.byref(chars_read))
if not self.fast_mode:
ctypes.windll.kernel32.ReadConsoleOutputAttribute(self.stdout, ctypes.byref(self.ac), self.buffer_width, coord, ctypes.byref(chars_read))
t = self.tc.value
a = self.ac.value
if not self.fast_mode:
a = self.ac.value
# add data
if i >= len(self.data):
self.data.append(t)
self.attributes.append(a)
else:
self.data[i] = t
for j in range(len(self.data), i + 1):
self.data.append('')
if not self.fast_mode:
self.attributes.append('')
self.data[i] = t
if not self.fast_mode:
self.attributes[i] = a
#for i in range(0, len(t)):
# write new output to shared memory
if self.mem_redraw_ct == CONQUE_SOLE_MEM_REDRAW:
self.mem_redraw_ct = 0
try:
if self.mem_redraw_ct == CONQUE_SOLE_MEM_REDRAW:
self.mem_redraw_ct = 0
self.shm_output.write(''.join(self.data))
self.shm_attributes.write(''.join(self.attributes))
else:
for i in range(0, len(self.data)):
self.shm_output.write(text=self.data[i], start=self.buffer_width * i)
if not self.fast_mode:
self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i)
else:
self.shm_output.write(text=''.join(self.data[read_start:read_end]), start=read_start * self.buffer_width)
self.shm_attributes.write(text=''.join(self.attributes[read_start:read_end]), start=read_start * self.buffer_width)
for i in range(read_start, read_end):
self.shm_output.write(text=self.data[i], start=self.buffer_width * i)
if not self.fast_mode:
self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i)
#self.shm_output.write(text=''.join(self.data[read_start:read_end]), start=read_start * self.buffer_width)
#self.shm_attributes.write(text=''.join(self.attributes[read_start:read_end]), start=read_start * self.buffer_width)
# write cursor position to shared memory
stats = {'top_offset': buf_info.srWindow.Top, 'default_attribute': buf_info.wAttributes, 'cursor_x': curs_col, 'cursor_y': curs_line, 'is_alive': 1}
self.shm_stats.write(stats)
# write cursor position to shared memory
stats = {'top_offset': buf_info.srWindow.Top, 'default_attribute': buf_info.wAttributes, 'cursor_x': curs_col, 'cursor_y': curs_line, 'is_alive': 1}
self.shm_stats.write(stats)
# adjust screen position
self.top = buf_info.srWindow.Top
self.cursor_line = curs_line
# check for reset
if curs_line > buf_info.dwSize.Y - 200:
self.reset_console(buf_info)
except:
# adjust screen position
self.top = buf_info.srWindow.Top
self.cursor_line = curs_line
# check for reset
if curs_line > buf_info.dwSize.Y - 200:
self.reset_console(buf_info)
pass
# increment redraw counters
self.screen_redraw_ct += 1
@ -415,12 +420,9 @@ class ConqueSoleSubprocess():
return None
# }}}
# ****************************************************************************
# clear the console and set cursor at home position
def reset_console(self, buf_info, add_block=True): # {{{
def reset_console(self, buf_info, add_block=True):
""" Extend the height of the current console if the cursor postion gets within 200 lines of the current size. """
# sometimes we just want to change the buffer width,
# in which case no need to add another block
@ -431,8 +433,9 @@ class ConqueSoleSubprocess():
self.shm_output.close()
self.shm_output = None
self.shm_attributes.close()
self.shm_attributes = None
if not self.fast_mode:
self.shm_attributes.close()
self.shm_attributes = None
# new shared memory key
mem_key = 'mk' + str(time.time())
@ -448,15 +451,17 @@ class ConqueSoleSubprocess():
self.data[i] = self.data[i] + ' ' * (self.buffer_width - len(self.data[i]))
self.shm_output.write(''.join(self.data))
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
if not self.fast_mode:
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
# backfill attributes
if len(self.attributes[0]) < self.buffer_width:
for i in range(0, len(self.attributes)):
self.attributes[i] = self.attributes[i] + chr(buf_info.wAttributes) * (self.buffer_width - len(self.attributes[i]))
self.shm_attributes.write(''.join(self.attributes))
if not self.fast_mode:
self.shm_attributes.write(''.join(self.attributes))
# notify wrapper of new output block
self.shm_rescroll.write({'cmd': 'new_output', 'data': {'blocks': self.output_blocks, 'mem_key': mem_key}})
@ -481,19 +486,20 @@ class ConqueSoleSubprocess():
self.tc = ctypes.create_unicode_buffer(self.buffer_width)
self.ac = ctypes.create_unicode_buffer(self.buffer_width)
# }}}
# ****************************************************************************
# write text to console. this function just parses out special sequences for
# special key events and passes on the text to the plain or virtual key functions
def write(self): # {{{
def write(self):
""" Write text to console.
This function just parses out special sequences for special key events
and passes on the text to the plain or virtual key functions.
"""
# get input from shared mem
text = self.shm_input.read()
# nothing to do here
if text == '':
if text == u(''):
return
@ -502,7 +508,7 @@ class ConqueSoleSubprocess():
self.shm_input.clear()
# split on VK codes
chunks = CONQUE_SEQ_REGEX_VK.split(text)
chunks = CONQUE_WIN32_REGEX_VK.split(text)
# if len() is one then no vks
if len(chunks) == 1:
@ -517,45 +523,48 @@ class ConqueSoleSubprocess():
if t == '':
continue
if CONQUE_SEQ_REGEX_VK.match(t):
if CONQUE_WIN32_REGEX_VK.match(t):
self.write_vk(t[2:-2])
else:
self.write_plain(t)
# }}}
# ****************************************************************************
def write_plain(self, text): # {{{
def write_plain(self, text):
""" Write simple text to subprocess. """
li = INPUT_RECORD * len(text)
list_input = li()
for i in range(0, len(text)):
# create keyboard input
ke = KEY_EVENT_RECORD()
ke.bKeyDown = ctypes.c_byte(1)
ke.wRepeatCount = ctypes.c_short(1)
cnum = ord(text[i])
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum)
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(cnum), 0))
if cnum > 31:
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
elif cnum == 3:
ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, self.pid)
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96)
ke.dwControlKeyState = LEFT_CTRL_PRESSED
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
else:
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
if cnum in CONQUE_WINDOWS_VK_INV:
ke.wVirtualKeyCode = cnum
else:
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96)
ke.dwControlKeyState = LEFT_CTRL_PRESSED
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
kc = INPUT_RECORD(KEY_EVENT)
kc.Event.KeyEvent = ke
@ -574,27 +583,41 @@ class ConqueSoleSubprocess():
# }}}
def write_vk(self, vk_code):
""" Write special characters to console subprocess. """
# ****************************************************************************
def write_vk(self, vk_code): # {{{
code = None
ctrl_pressed = False
# this could be made more generic when more attributes
# other than ctrl_pressed are available
vk_attributes = vk_code.split(';')
for attr in vk_attributes:
if attr == CONQUE_VK_ATTR_CTRL_PRESSED:
ctrl_pressed = True
else:
code = attr
li = INPUT_RECORD * 1
# create keyboard input
ke = KEY_EVENT_RECORD()
ke.uChar.UnicodeChar = u(chr(0))
ke.wVirtualKeyCode = ctypes.c_short(int(vk_code))
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(vk_code), 0))
ke.uChar.UnicodeChar = uchr(0)
ke.wVirtualKeyCode = ctypes.c_short(int(code))
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(code), 0))
ke.bKeyDown = ctypes.c_byte(1)
ke.wRepeatCount = ctypes.c_short(1)
# set enhanced key mode for arrow keys
if vk_code in CONQUE_WINDOWS_VK_ENHANCED:
if code in CONQUE_WINDOWS_VK_ENHANCED:
ke.dwControlKeyState = ENHANCED_KEY
ke.dwControlKeyState |= ENHANCED_KEY
if ctrl_pressed:
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
kc = INPUT_RECORD(KEY_EVENT)
kc.Event.KeyEvent = ke
@ -610,11 +633,8 @@ class ConqueSoleSubprocess():
# }}}
# ****************************************************************************
def close(self): # {{{
def close(self):
""" Close all running subproccesses """
# record status
self.is_alive = False
@ -656,18 +676,18 @@ class ConqueSoleSubprocess():
pass
def close_pid(self, pid):
""" Terminate a single process. """
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid)
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)
# }}}
# ****************************************************************************
# check process health
def is_alive(self): # {{{
def is_alive(self):
""" Check process health. """
status = ctypes.windll.kernel32.WaitForSingleObject(self.handle, 1)
@ -677,21 +697,15 @@ class ConqueSoleSubprocess():
return self.is_alive
# }}}
# ****************************************************************************
# return screen data as string
def get_screen_text(self): # {{{
def get_screen_text(self):
""" Return screen data as string. """
return "\n".join(self.data)
# }}}
# ****************************************************************************
def set_window_size(self, width, height): # {{{
def set_window_size(self, width, height):
""" Change Windows console size. """
@ -735,19 +749,14 @@ class ConqueSoleSubprocess():
self.window_width = buf_info.srWindow.Right + 1
self.window_height = buf_info.srWindow.Bottom + 1
# }}}
# ****************************************************************************
# get buffer info, used a lot
def get_buffer_info(self): # {{{
def get_buffer_info(self):
""" Retrieve commonly-used buffer information. """
buf_info = CONSOLE_SCREEN_BUFFER_INFO()
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(self.stdout, ctypes.byref(buf_info))
return buf_info
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_wrapper.py {{{
# FILE: autoload/conque_term/conque_sole_wrapper.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,15 +25,17 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
""" ConqueSoleSubprocessWrapper {{{
"""
ConqueSoleSubprocessWrapper
Subprocess wrapper to deal with Windows insanity. Launches console based python,
which in turn launches originally requested command. Communicates with cosole
python through shared memory objects.
}}} """
"""
import ctypes
import time
@ -41,8 +43,7 @@ import time
class ConqueSoleWrapper():
# class properties {{{
# unique key used for shared memory block names
shm_key = ''
# process info
@ -53,7 +54,6 @@ class ConqueSoleWrapper():
bucket = None
# console size
# NOTE: columns should never change after open() is called
lines = 24
columns = 80
@ -69,33 +69,31 @@ class ConqueSoleWrapper():
# console python process
proc = None
# }}}
#########################################################################
# unused
def open(self, cmd, lines, columns, python_exe='python.exe', communicator_py='conque_sole_communicator.py', options={}):
""" Launch python.exe subprocess which will in turn launch the user's program.
def __init__(self): # {{{
Arguments:
cmd -- The user's command to run. E.g. "Powershell.exe" or "C:\Python27\Scripts\ipython.bat"
lines, columns -- The size of the console, also the size of the Vim buffer
python.exe -- The path to the python executable, typically C:\PythonXX\python.exe
communicator_py -- The path to the subprocess controller script in the user's vimfiles directory
options -- optional configuration
"""
self.lines = lines
self.columns = columns
self.bucket = u('')
# }}}
#########################################################################
# run communicator process which will in turn run cmd
def open(self, cmd, options={}, python_exe='python.exe', communicator_py='conque_sole_communicator.py'): # {{{
self.lines = options['LINES']
self.columns = options['COLUMNS']
# create a shm key
self.shm_key = 'mk' + str(time.time())
# python command
cmd_line = '%s "%s" %s %d %d %s' % (python_exe, communicator_py, self.shm_key, int(self.columns), int(self.lines), cmd)
cmd_line = '%s "%s" %s %d %d %d %d %s' % (python_exe, communicator_py, self.shm_key, int(self.columns), int(self.lines), int(options['CODE_PAGE']), int(CONQUE_FAST_MODE), cmd)
# console window attributes
flags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS
flags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT
si = STARTUPINFO()
pi = PROCESS_INFORMATION()
@ -114,13 +112,13 @@ class ConqueSoleWrapper():
# init shared memory objects
self.init_shared_memory(self.shm_key)
# }}}
#########################################################################
# read output from shared memory
def read(self, start_line, num_lines, timeout=0):
""" Read a range of console lines from shared memory.
def read(self, start_line, num_lines, timeout=0): # {{{
Returns a pair of lists containing the console text and console text attributes.
"""
# emulate timeout by sleeping timeout time
if timeout > 0:
read_timeout = float(timeout) / 1000
@ -133,16 +131,14 @@ class ConqueSoleWrapper():
# get output
for i in range(start_line, start_line + num_lines + 1):
output.append(self.shm_output.read(self.columns, i * self.columns))
attributes.append(self.shm_attributes.read(self.columns, i * self.columns))
if not CONQUE_FAST_MODE:
attributes.append(self.shm_attributes.read(self.columns, i * self.columns))
return (output, attributes)
# }}}
#########################################################################
# get current cursor/scroll position
def get_stats(self): # {{{
def get_stats(self):
""" Return a dictionary with current console cursor and scrolling information. """
try:
rescroll = self.shm_rescroll.read()
@ -156,16 +152,18 @@ class ConqueSoleWrapper():
self.shm_output.close()
self.shm_output = None
self.shm_attributes.close()
self.shm_attributes = None
if not CONQUE_FAST_MODE:
self.shm_attributes.close()
self.shm_attributes = None
# reallocate memory
self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'output', rescroll['data']['mem_key'], True)
self.shm_output.create('read')
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'attributes', rescroll['data']['mem_key'], True, encoding='latin-1')
self.shm_attributes.create('read')
if not CONQUE_FAST_MODE:
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'attributes', rescroll['data']['mem_key'], True, encoding='latin-1')
self.shm_attributes.create('read')
stats_str = self.shm_stats.read()
if stats_str != '':
@ -178,12 +176,10 @@ class ConqueSoleWrapper():
return self.stats
# }}}
#########################################################################
# get process status
def is_alive(self):
""" Get process status. """
def is_alive(self): # {{{
if not self.shm_stats:
return True
@ -192,16 +188,12 @@ class ConqueSoleWrapper():
return (stats_str['is_alive'])
else:
return True
# }}}
#########################################################################
# write input to shared memory
def write(self, text): # {{{
self.bucket += u(text, 'ascii', 'replace')
def write(self, text):
""" Write input to shared memory. """
self.bucket += text
istr = self.shm_input.read()
@ -210,51 +202,36 @@ class ConqueSoleWrapper():
self.shm_input.write(self.bucket[:500])
self.bucket = self.bucket[500:]
# }}}
#########################################################################
# write virtual key code to shared memory using proprietary escape seq
def write_vk(self, vk_code):
""" Write virtual key code to shared memory using proprietary escape sequences. """
def write_vk(self, vk_code): # {{{
seq = "\x1b[" + str(vk_code) + "VK"
seq = u("\x1b[") + u(str(vk_code)) + u("VK")
self.write(seq)
# }}}
#########################################################################
# idle
def idle(self): # {{{
def idle(self):
""" Write idle command to shared memory block, so subprocess controller can hibernate. """
self.shm_command.write({'cmd': 'idle', 'data': {}})
# }}}
#########################################################################
# resume
def resume(self): # {{{
def resume(self):
""" Write resume command to shared memory block, so subprocess controller can wake up. """
self.shm_command.write({'cmd': 'resume', 'data': {}})
# }}}
#########################################################################
# shut it all down
def close(self): # {{{
def close(self):
""" Shut it all down. """
self.shm_command.write({'cmd': 'close', 'data': {}})
time.sleep(0.2)
# }}}
#########################################################################
# resize console window
def window_resize(self, lines, columns): # {{{
def window_resize(self, lines, columns):
""" Resize console window. """
self.lines = lines
@ -264,12 +241,9 @@ class ConqueSoleWrapper():
self.shm_resize.write({'cmd': 'resize', 'data': {'width': columns, 'height': lines}})
# }}}
# ****************************************************************************
# create shared memory objects
def init_shared_memory(self, mem_key): # {{{
def init_shared_memory(self, mem_key):
""" Create shared memory objects. """
self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key)
self.shm_input.create('write')
@ -278,8 +252,9 @@ class ConqueSoleWrapper():
self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'output', mem_key, True)
self.shm_output.create('write')
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'attributes', mem_key, True, encoding='latin-1')
self.shm_attributes.create('write')
if not CONQUE_FAST_MODE:
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'attributes', mem_key, True, encoding='latin-1')
self.shm_attributes.create('write')
self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True)
self.shm_stats.create('write')
@ -299,6 +274,5 @@ class ConqueSoleWrapper():
return True
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_subprocess.py {{{
# FILE: autoload/conque_term/conque_subprocess.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,7 +25,7 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""
ConqueSubprocess
@ -43,15 +43,15 @@ Usage:
p.close()
"""
if CONQUE_PLATFORM == 'nix':
import os
import signal
import pty
import tty
import select
import fcntl
import termios
import struct
import os
import signal
import pty
import tty
import select
import fcntl
import termios
import struct
import shlex
class ConqueSubprocess:
@ -62,16 +62,12 @@ class ConqueSubprocess:
# stdout+stderr file descriptor
fd = None
# constructor
def __init__(self): # {{{
self.pid = 0
# }}}
# create pty + subprocess
def open(self, command, env={}): # {{{
def open(self, command, env={}):
""" Create subprocess using forkpty() """
# parse command
command_arr = command.split()
command_arr = shlex.split(command)
executable = command_arr[0]
args = command_arr
@ -90,7 +86,7 @@ class ConqueSubprocess:
for k in env.keys():
os.environ[k] = env[k]
# set some attributes
# set tty attributes
try:
attrs = tty.tcgetattr(1)
attrs[0] = attrs[0] ^ tty.IGNBRK
@ -111,14 +107,13 @@ class ConqueSubprocess:
else:
pass
# }}}
# read from pty
# XXX - select.poll() doesn't work in OS X!!!!!!!
def read(self, timeout=1): # {{{
def read(self, timeout=1):
""" Read from subprocess and return new output """
output = ''
read_timeout = float(timeout) / 1000
read_ct = 0
try:
# read from fd until no more output
@ -128,49 +123,59 @@ class ConqueSubprocess:
lines = ''
for s_fd in s_read:
try:
lines = os.read(self.fd, 32)
# increase read buffer so huge reads don't slow down
if read_ct < 10:
lines = os.read(self.fd, 32)
elif read_ct < 50:
lines = os.read(self.fd, 512)
else:
lines = os.read(self.fd, 2048)
read_ct += 1
except:
pass
output = output + lines.decode('utf-8')
if lines == '':
if lines == '' or read_ct > 100:
break
except:
pass
return output
# }}}
# I guess this one's not bad
def write(self, input): # {{{
def write(self, input):
""" Write new input to subprocess """
try:
if CONQUE_PYTHON_VERSION == 2:
os.write(self.fd, input)
os.write(self.fd, input.encode('utf-8', 'ignore'))
else:
os.write(self.fd, bytes(input, 'utf-8'))
except:
pass
# }}}
# signal process
def signal(self, signum): # {{{
def signal(self, signum):
""" signal process """
try:
os.kill(self.pid, signum)
except:
pass
# }}}
# close process
def close(self): # {{{
def close(self):
""" close process with sigterm signal """
self.signal(15)
# }}}
# get process status
def is_alive(self): #{{{
def is_alive(self):
""" get process status """
p_status = True
try:
if os.waitpid(self.pid, os.WNOHANG)[0]:
p_status = False
@ -179,17 +184,15 @@ class ConqueSubprocess:
return p_status
# }}}
# update window size in kernel, then send SIGWINCH to fg process
def window_resize(self, lines, columns): # {{{
def window_resize(self, lines, columns):
""" update window size in kernel, then send SIGWINCH to fg process """
try:
fcntl.ioctl(self.fd, termios.TIOCSWINSZ, struct.pack("HHHH", lines, columns, 0, 0))
os.kill(self.pid, signal.SIGWINCH)
except:
pass
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_win32_util.py {{{
# FILE: autoload/conque_term/conque_win32_util.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,15 +25,15 @@
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. }}}
# THE SOFTWARE.
"""Python structures used for ctypes interaction"""
""" Python constants and structures used for ctypes interaction. """
from ctypes import *
# Constants
# create process flag constants {{{
# create process flag constants
CREATE_BREAKAWAY_FROM_JOB = 0x01000000
CREATE_DEFAULT_ERROR_MODE = 0x04000000
@ -46,15 +46,14 @@ CREATE_SEPARATE_WOW_VDM = 0x00000800
CREATE_SHARED_WOW_VDM = 0x00001000
CREATE_SUSPENDED = 0x00000004
CREATE_UNICODE_ENVIRONMENT = 0x00000400
DEBUG_ONLY_THIS_PROCESS = 0x00000002
DEBUG_PROCESS = 0x00000001
DETACHED_PROCESS = 0x00000008
EXTENDED_STARTUPINFO_PRESENT = 0x00080000
INHERIT_PARENT_AFFINITY = 0x00010000
# }}}
# process priority constants {{{
# process priority constants
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
@ -63,9 +62,8 @@ IDLE_PRIORITY_CLASS = 0x00000040
NORMAL_PRIORITY_CLASS = 0x00000020
REALTIME_PRIORITY_CLASS = 0x00000100
# }}}
# startup info constants {{{
# startup info constants
STARTF_FORCEONFEEDBACK = 0x00000040
STARTF_FORCEOFFFEEDBACK = 0x00000080
@ -81,9 +79,8 @@ STARTF_USESHOWWINDOW = 0x00000001
STARTF_USESIZE = 0x00000002
STARTF_USESTDHANDLES = 0x00000100
# }}}
# show window constants {{{
# show window constants
SW_FORCEMINIMIZE = 11
SW_HIDE = 0
@ -99,9 +96,8 @@ SW_SHOWNA = 8
SW_SHOWNOACTIVATE = 4
SW_SHOWNORMAL = 1
# }}}
# input event types {{{
# input event types
FOCUS_EVENT = 0x0010
KEY_EVENT = 0x0001
@ -109,9 +105,8 @@ MENU_EVENT = 0x0008
MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004
# }}}
# key event modifiers {{{
# key event modifiers
CAPSLOCK_ON = 0x0080
ENHANCED_KEY = 0x0100
@ -123,9 +118,8 @@ RIGHT_CTRL_PRESSED = 0x0004
SCROLLLOCK_ON = 0x0040
SHIFT_PRESSED = 0x0010
# }}}
# process access {{{
# process access
PROCESS_CREATE_PROCESS = 0x0080
PROCESS_CREATE_THREAD = 0x0002
@ -140,17 +134,15 @@ PROCESS_VM_OPERATION = 0x0008
PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
# }}}
# input / output handles {{{
# input / output handles
STD_INPUT_HANDLE = c_ulong(-10)
STD_OUTPUT_HANDLE = c_ulong(-11)
STD_ERROR_HANDLE = c_ulong(-12)
# }}}
CONQUE_WINDOWS_VK = { # {{{
CONQUE_WINDOWS_VK = {
'VK_LBUTTON': 0x0001,
'VK_RBUTTON': 0x0002,
'VK_CANCEL': 0x0003,
@ -280,19 +272,16 @@ CONQUE_WINDOWS_VK_ENHANCED = {
str(int(CONQUE_WINDOWS_VK['VK_END'])): 1
}
# }}}
# structures used for CreateProcess
# Odd types {{{
# Odd types
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
# }}}
class STARTUPINFO(Structure): # {{{
class STARTUPINFO(Structure):
_fields_ = [("cb", c_ulong),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
@ -315,9 +304,8 @@ class STARTUPINFO(Structure): # {{{
def to_str(self):
return ''
# }}}
class PROCESS_INFORMATION(Structure): # {{{
class PROCESS_INFORMATION(Structure):
_fields_ = [("hProcess", c_void_p),
("hThread", c_void_p),
("dwProcessId", c_ulong),
@ -326,9 +314,8 @@ class PROCESS_INFORMATION(Structure): # {{{
def to_str(self):
return ''
# }}}
class MEMORY_BASIC_INFORMATION(Structure): # {{{
class MEMORY_BASIC_INFORMATION(Structure):
_fields_ = [("BaseAddress", c_void_p),
("AllocationBase", c_void_p),
("AllocationProtect", c_ulong),
@ -340,9 +327,8 @@ class MEMORY_BASIC_INFORMATION(Structure): # {{{
def to_str(self):
return ''
# }}}
class SECURITY_ATTRIBUTES(Structure): # {{{
class SECURITY_ATTRIBUTES(Structure):
_fields_ = [("Length", c_ulong),
("SecDescriptor", c_void_p),
("InheritHandle", c_bool)]
@ -350,18 +336,16 @@ class SECURITY_ATTRIBUTES(Structure): # {{{
def to_str(self):
return ''
# }}}
class COORD(Structure): # {{{
class COORD(Structure):
_fields_ = [("X", c_short),
("Y", c_short)]
def to_str(self):
return ''
# }}}
class SMALL_RECT(Structure): # {{{
class SMALL_RECT(Structure):
_fields_ = [("Left", c_short),
("Top", c_short),
("Right", c_short),
@ -370,9 +354,8 @@ class SMALL_RECT(Structure): # {{{
def to_str(self):
return ''
# }}}
class CONSOLE_SCREEN_BUFFER_INFO(Structure): # {{{
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
_fields_ = [("dwSize", COORD),
("dwCursorPosition", COORD),
("wAttributes", c_short),
@ -382,27 +365,24 @@ class CONSOLE_SCREEN_BUFFER_INFO(Structure): # {{{
def to_str(self):
return ''
# }}}
class CHAR_UNION(Union): # {{{
class CHAR_UNION(Union):
_fields_ = [("UnicodeChar", c_wchar),
("AsciiChar", c_char)]
def to_str(self):
return ''
# }}}
class CHAR_INFO(Structure): # {{{
class CHAR_INFO(Structure):
_fields_ = [("Char", CHAR_UNION),
("Attributes", c_short)]
def to_str(self):
return ''
# }}}
class KEY_EVENT_RECORD(Structure): # {{{
class KEY_EVENT_RECORD(Structure):
_fields_ = [("bKeyDown", c_byte),
("pad2", c_byte),
('pad1', c_short),
@ -415,9 +395,8 @@ class KEY_EVENT_RECORD(Structure): # {{{
def to_str(self):
return ''
# }}}
class MOUSE_EVENT_RECORD(Structure): # {{{
class MOUSE_EVENT_RECORD(Structure):
_fields_ = [("dwMousePosition", COORD),
("dwButtonState", c_int),
("dwControlKeyState", c_int),
@ -426,32 +405,29 @@ class MOUSE_EVENT_RECORD(Structure): # {{{
def to_str(self):
return ''
# }}}
class WINDOW_BUFFER_SIZE_RECORD(Structure): # {{{
class WINDOW_BUFFER_SIZE_RECORD(Structure):
_fields_ = [("dwSize", COORD)]
def to_str(self):
return ''
# }}}
class MENU_EVENT_RECORD(Structure): # {{{
class MENU_EVENT_RECORD(Structure):
_fields_ = [("dwCommandId", c_uint)]
def to_str(self):
return ''
# }}}
class FOCUS_EVENT_RECORD(Structure): # {{{
class FOCUS_EVENT_RECORD(Structure):
_fields_ = [("bSetFocus", c_byte)]
def to_str(self):
return ''
# }}}
class INPUT_UNION(Union): # {{{
class INPUT_UNION(Union):
_fields_ = [("KeyEvent", KEY_EVENT_RECORD),
("MouseEvent", MOUSE_EVENT_RECORD),
("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD),
@ -460,14 +436,13 @@ class INPUT_UNION(Union): # {{{
def to_str(self):
return ''
# }}}
class INPUT_RECORD(Structure): # {{{
class INPUT_RECORD(Structure):
_fields_ = [("EventType", c_short),
("Event", INPUT_UNION)]
def to_str(self):
return ''
# }}}
# vim:foldmethod=marker