parent
520e6e1e52
commit
5cf89f0976
|
@ -7,9 +7,11 @@ import util, window2
|
||||||
from point2 import Point
|
from point2 import Point
|
||||||
|
|
||||||
# modes
|
# modes
|
||||||
# TODO: mode_c mode_nasm mode_console mode_sh mode_sql mode_javascript mode_diff mode_tt
|
# TODO: mode_c mode_nasm mode_sh mode_sql mode_javascript mode_diff mode_tt
|
||||||
import mode2
|
import mode2
|
||||||
import mode_mini, mode_search, mode_replace, mode_blame, mode_which, mode_diff
|
import mode_mini, mode_search, mode_replace, mode_which
|
||||||
|
import mode_console, mode_consolemini
|
||||||
|
import mode_blame, mode_diff
|
||||||
import mode_python, mode_perl, mode_xml
|
import mode_python, mode_perl, mode_xml
|
||||||
import mode_life, mode_text, mode_mutt
|
import mode_life, mode_text, mode_mutt
|
||||||
|
|
||||||
|
@ -81,7 +83,8 @@ class Application(object):
|
||||||
self.modes = {
|
self.modes = {
|
||||||
'blame': mode_blame.Blame,
|
'blame': mode_blame.Blame,
|
||||||
# 'c': mode_c.C,
|
# 'c': mode_c.C,
|
||||||
# 'console': mode_console.Console,
|
'console': mode_console.Console,
|
||||||
|
'consolemini': mode_consolemini.Console,
|
||||||
'diff': mode_diff.Diff,
|
'diff': mode_diff.Diff,
|
||||||
'fundamental': mode2.Fundamental,
|
'fundamental': mode2.Fundamental,
|
||||||
'mini': mode_mini.Mini,
|
'mini': mode_mini.Mini,
|
||||||
|
@ -161,11 +164,13 @@ class Application(object):
|
||||||
buffers.append(buffer2.ConsoleBuffer())
|
buffers.append(buffer2.ConsoleBuffer())
|
||||||
self.bufferlist = bufferlist.BufferList(height, width)
|
self.bufferlist = bufferlist.BufferList(height, width)
|
||||||
self.active_slot = 0
|
self.active_slot = 0
|
||||||
#self.resize_slots()
|
|
||||||
|
|
||||||
# build windows for our buffers
|
# build windows for our buffers
|
||||||
for b in buffers:
|
for b in buffers:
|
||||||
window2.Window(b, self, height, width, mode_name=init_mode)
|
if b.name() == '*Console*':
|
||||||
|
window2.Window(b, self, height, width, mode_name='console')
|
||||||
|
else:
|
||||||
|
window2.Window(b, self, height, width, mode_name=init_mode)
|
||||||
self.bufferlist.add_buffer(b)
|
self.bufferlist.add_buffer(b)
|
||||||
self.bufferlist.set_slot(0, buffers[0])
|
self.bufferlist.set_slot(0, buffers[0])
|
||||||
|
|
||||||
|
|
|
@ -890,10 +890,10 @@ class OpenConsole(Method):
|
||||||
if not a.has_buffer_name('*Console*'):
|
if not a.has_buffer_name('*Console*'):
|
||||||
a.add_buffer(buffer2.ConsoleBuffer())
|
a.add_buffer(buffer2.ConsoleBuffer())
|
||||||
b = a.bufferlist.get_buffer_by_name('*Console*')
|
b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||||
if a.w().buffer is not b:
|
if a.window().buffer is not b:
|
||||||
a.switch_buffer(b)
|
a.switch_buffer(b)
|
||||||
f = lambda x: None
|
f = lambda x: None
|
||||||
w.application.open_mini_buffer('>>> ', f, self, None, 'console')
|
w.application.open_mini_buffer('>>> ', f, self, None, 'consolemini')
|
||||||
|
|
||||||
class ShellCmd(Method):
|
class ShellCmd(Method):
|
||||||
'''Run a command in a shell and put the output in a new buffer'''
|
'''Run a command in a shell and put the output in a new buffer'''
|
||||||
|
|
173
mode_console.py
173
mode_console.py
|
@ -1,158 +1,25 @@
|
||||||
import code, os, sets, string, StringIO, sys, traceback
|
import code, string, StringIO, sys, traceback
|
||||||
|
import color, completer, method, mode2
|
||||||
|
from lex2 import Grammar, PatternRule
|
||||||
|
from point2 import Point
|
||||||
|
|
||||||
import color, completer, default, highlight, method, mode, point
|
class ConsoleGrammar(Grammar):
|
||||||
|
rules = [
|
||||||
|
PatternRule(name=r'mesg', pattern=r'^[A-Za-z].*$'),
|
||||||
|
PatternRule(name=r'input', pattern=r'^>>>.*$'),
|
||||||
|
PatternRule(name=r'input2', pattern=r'^-->.*$'),
|
||||||
|
PatternRule(name=r'output', pattern=r'^ .*$'),
|
||||||
|
]
|
||||||
|
|
||||||
class Console(mode.Fundamental):
|
class Console(mode2.Fundamental):
|
||||||
|
grammar = ConsoleGrammar()
|
||||||
def __init__(self, w):
|
def __init__(self, w):
|
||||||
mode.Fundamental.__init__(self, w)
|
mode2.Fundamental.__init__(self, w)
|
||||||
|
self.colors = {
|
||||||
self.actions = {}
|
'mesg': color.build('blue', 'default'),
|
||||||
self.bindings = {}
|
'input': color.build('cyan', 'default'),
|
||||||
self.globals = dict(w.application.globals())
|
'input2': color.build('cyan', 'default'),
|
||||||
self.locals = dict(w.application.locals())
|
'output': color.build('default', 'default'),
|
||||||
self.saved_input = ""
|
}
|
||||||
|
|
||||||
self.add_bindings('start-of-line', ('C-a', 'HOME',))
|
|
||||||
self.add_bindings('end-of-line', ('C-e', 'END',))
|
|
||||||
self.add_bindings('backward', ('C-b', 'L_ARROW',))
|
|
||||||
self.add_bindings('forward', ('C-f', 'R_ARROW',))
|
|
||||||
self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',))
|
|
||||||
self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',))
|
|
||||||
self.add_bindings('delete-right', ('C-d',))
|
|
||||||
self.add_bindings('delete-right-word', ('M-d',))
|
|
||||||
self.add_bindings('kill-region', ('C-w',))
|
|
||||||
self.add_bindings('copy-region', ('M-w',))
|
|
||||||
self.add_bindings('kill', ('C-k',))
|
|
||||||
self.add_bindings('copy', ('M-k',))
|
|
||||||
self.add_bindings('yank', ('C-y',))
|
|
||||||
self.add_bindings('pop-kill', ('M-y',))
|
|
||||||
self.add_bindings('right-word', ('M-f',))
|
|
||||||
self.add_bindings('left-word', ('M-b',))
|
|
||||||
self.add_bindings('set-mark', ('C-@',))
|
|
||||||
self.add_bindings('switch-mark', ('C-x C-x',))
|
|
||||||
self.add_bindings('undo', ('C-/', 'C-x u',))
|
|
||||||
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
|
|
||||||
self.add_bindings('toggle-margins', ('M-m',))
|
|
||||||
self.add_bindings('transpose-words', ('M-t',))
|
|
||||||
self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',))
|
|
||||||
self.add_bindings('delete-right-whitespace', ('C-c d',))
|
|
||||||
self.add_bindings('insert-space', ('SPACE',))
|
|
||||||
self.add_bindings('insert-tab', ('TAB',))
|
|
||||||
|
|
||||||
self.add_action_and_bindings(ConsoleExec(), ('RETURN',))
|
|
||||||
self.add_action_and_bindings(ConsoleCancel(), ('C-]',))
|
|
||||||
#self.add_action_and_bindings(ConsoleTab(), ('TAB',))
|
|
||||||
|
|
||||||
# create all the insert actions for the character ranges we like
|
|
||||||
for c in string.letters + string.digits + string.punctuation:
|
|
||||||
self.add_binding('insert-string-%s' % c, c)
|
|
||||||
|
|
||||||
# get mode name
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Console"
|
return "Console"
|
||||||
|
|
||||||
class ConsoleExec(method.Method):
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
s = w.buffer.make_string()
|
|
||||||
w.buffer.set_data('')
|
|
||||||
a = w.application
|
|
||||||
|
|
||||||
if not a.has_buffer_name('*Console*'):
|
|
||||||
a.add_buffer(buffer.ConsoleBuffer())
|
|
||||||
b = a.bufferlist.get_buffer_by_name('*Console*')
|
|
||||||
if a.window().buffer is not b:
|
|
||||||
a.switch_buffer(b)
|
|
||||||
p = a.get_mini_buffer_prompt()
|
|
||||||
b.insert_string(b.get_buffer_end(), p + s + '\n', force=True)
|
|
||||||
|
|
||||||
if w.mode.saved_input:
|
|
||||||
s = w.mode.saved_input + '\n' + s
|
|
||||||
|
|
||||||
try:
|
|
||||||
code_obj = code.compile_command(s)
|
|
||||||
if code_obj is None:
|
|
||||||
w.mode.saved_input = s
|
|
||||||
a.set_mini_buffer_prompt(' > ')
|
|
||||||
output = None
|
|
||||||
else:
|
|
||||||
w.mode.saved_input = ''
|
|
||||||
a.set_mini_buffer_prompt('>>> ')
|
|
||||||
sys.stdout = code_out = StringIO.StringIO()
|
|
||||||
sys.stderr = code_err = StringIO.StringIO()
|
|
||||||
ok = True
|
|
||||||
try:
|
|
||||||
#exec code_obj in a.globals(), a.locals()
|
|
||||||
exec code_obj in w.mode.globals, w.mode.locals
|
|
||||||
except Exception, e:
|
|
||||||
ok = False
|
|
||||||
output = str(e) + '\n'
|
|
||||||
sys.stdout = sys.__stdout__
|
|
||||||
sys.stdout = sys.__stderr__
|
|
||||||
if ok:
|
|
||||||
output = code_out.getvalue()
|
|
||||||
code_out.close()
|
|
||||||
code_err.close()
|
|
||||||
except (SyntaxError, OverflowError, ValueError), e:
|
|
||||||
a.set_mini_buffer_prompt('>>> ')
|
|
||||||
#t = sys.last_traceback
|
|
||||||
t = sys.exc_traceback
|
|
||||||
output = str(e) + traceback.format_exc()
|
|
||||||
|
|
||||||
#try:
|
|
||||||
# output = a.eval(s)
|
|
||||||
#except Exception, e:
|
|
||||||
# output = str(e)
|
|
||||||
if output:
|
|
||||||
b.insert_string(b.get_buffer_end(), output, force=True)
|
|
||||||
w.goto_end()
|
|
||||||
|
|
||||||
class ConsoleCancel(method.Method):
|
|
||||||
def execute(self, w, **vargs):
|
|
||||||
w.application.close_mini_buffer()
|
|
||||||
|
|
||||||
#class ConsoleTab(method.Method):
|
|
||||||
# def execute(self, w, **vargs):
|
|
||||||
# a = w.application
|
|
||||||
# s = w.buffer.make_string()
|
|
||||||
#
|
|
||||||
# if '"' in s or "'" in s or "(" in s or ")" in s or "[" in s or "]" in s:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# parts = s.split(".")
|
|
||||||
# if len(parts) == 0:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# v = a.globals()
|
|
||||||
# v.update(a.locals())
|
|
||||||
# obj = None
|
|
||||||
# for part in parts[:-1]:
|
|
||||||
# if obj is None:
|
|
||||||
# if part in v:
|
|
||||||
# obj = v[part]
|
|
||||||
# else:
|
|
||||||
# return
|
|
||||||
# else:
|
|
||||||
# if hasattr(obj, part):
|
|
||||||
# obj = getattr(obj, part)
|
|
||||||
# else:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# if obj is None:
|
|
||||||
# pool = v.keys()
|
|
||||||
# else:
|
|
||||||
# pool = dir(obj)
|
|
||||||
# candidates = [x for x in pool if x.startswith(parts[-1])]
|
|
||||||
#
|
|
||||||
# if len(candidates) == 0:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# common = completer.find_common_string(candidates)
|
|
||||||
# s2 = '.'.join(parts[:-1]) + '.' + common
|
|
||||||
#
|
|
||||||
# w.buffer.set_data(s2)
|
|
||||||
#
|
|
||||||
# if len(candidates) > 1:
|
|
||||||
# if not a.has_buffer_name('*Console*'):
|
|
||||||
# a.add_buffer(buffer.ConsoleBuffer())
|
|
||||||
# b = a.bufferlist.get_buffer_by_name('*Console*')
|
|
||||||
# b.insert_string(b.get_buffer_end(), repr(candidates) + '\n', force=True)
|
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
import code, string, StringIO, sys, traceback
|
||||||
|
import color, completer, method, mode2
|
||||||
|
from lex2 import Grammar, PatternRule
|
||||||
|
from point2 import Point
|
||||||
|
|
||||||
|
class Console(mode2.Fundamental):
|
||||||
|
def __init__(self, w):
|
||||||
|
mode2.Fundamental.__init__(self, w)
|
||||||
|
self.bindings = {}
|
||||||
|
self.globals = dict(w.application.globals())
|
||||||
|
self.locals = dict(w.application.locals())
|
||||||
|
self.saved_input = ""
|
||||||
|
|
||||||
|
self.history = ['']
|
||||||
|
self.hindex = 0
|
||||||
|
|
||||||
|
self.add_bindings('start-of-line', ('C-a', 'HOME',))
|
||||||
|
self.add_bindings('end-of-line', ('C-e', 'END',))
|
||||||
|
self.add_bindings('backward', ('C-b', 'L_ARROW',))
|
||||||
|
self.add_bindings('forward', ('C-f', 'R_ARROW',))
|
||||||
|
self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',))
|
||||||
|
self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',))
|
||||||
|
self.add_bindings('delete-right', ('C-d',))
|
||||||
|
self.add_bindings('delete-right-word', ('M-d',))
|
||||||
|
self.add_bindings('kill-region', ('C-w',))
|
||||||
|
self.add_bindings('copy-region', ('M-w',))
|
||||||
|
self.add_bindings('kill', ('C-k',))
|
||||||
|
self.add_bindings('copy', ('M-k',))
|
||||||
|
self.add_bindings('yank', ('C-y',))
|
||||||
|
self.add_bindings('pop-kill', ('M-y',))
|
||||||
|
self.add_bindings('right-word', ('M-f',))
|
||||||
|
self.add_bindings('left-word', ('M-b',))
|
||||||
|
self.add_bindings('set-mark', ('C-@',))
|
||||||
|
self.add_bindings('switch-mark', ('C-x C-x',))
|
||||||
|
self.add_bindings('undo', ('C-/', 'C-x u',))
|
||||||
|
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
|
||||||
|
self.add_bindings('toggle-margins', ('M-m',))
|
||||||
|
self.add_bindings('transpose-words', ('M-t',))
|
||||||
|
self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',))
|
||||||
|
self.add_bindings('delete-right-whitespace', ('C-c d',))
|
||||||
|
self.add_bindings('insert-space', ('SPACE',))
|
||||||
|
self.add_bindings('insert-tab', ('TAB',))
|
||||||
|
self.add_action_and_bindings(ConsoleExec(), ('RETURN',))
|
||||||
|
self.add_action_and_bindings(ConsoleCancel(), ('C-]',))
|
||||||
|
self.add_action_and_bindings(ConsoleHistoryPrev(), ('C-p',))
|
||||||
|
self.add_action_and_bindings(ConsoleHistoryNext(), ('C-n',))
|
||||||
|
#self.add_action_and_bindings(ConsoleTab(), ('TAB',))
|
||||||
|
for c in string.letters + string.digits + string.punctuation:
|
||||||
|
self.add_binding('insert-string-%s' % c, c)
|
||||||
|
def name(self):
|
||||||
|
return "Console"
|
||||||
|
|
||||||
|
class ConsoleExec(method.Method):
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
s = w.buffer.make_string()
|
||||||
|
w.mode.history[-1] = s
|
||||||
|
w.mode.history.append('')
|
||||||
|
w.buffer.set_data('')
|
||||||
|
w.mode.hindex = len(w.mode.history) - 1
|
||||||
|
|
||||||
|
a = w.application
|
||||||
|
|
||||||
|
if not a.has_buffer_name('*Console*'):
|
||||||
|
raise Exception, "No console found!"
|
||||||
|
b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||||
|
if a.window().buffer is not b:
|
||||||
|
a.switch_buffer(b)
|
||||||
|
p = a.get_mini_buffer_prompt()
|
||||||
|
b.insert_string(b.get_buffer_end(), p + s + '\n', force=True)
|
||||||
|
|
||||||
|
if w.mode.saved_input:
|
||||||
|
s = w.mode.saved_input + '\n' + s
|
||||||
|
|
||||||
|
try:
|
||||||
|
code_obj = code.compile_command(s)
|
||||||
|
if code_obj is None:
|
||||||
|
w.mode.saved_input = s
|
||||||
|
a.set_mini_buffer_prompt('--> ')
|
||||||
|
output = None
|
||||||
|
else:
|
||||||
|
w.mode.saved_input = ''
|
||||||
|
a.set_mini_buffer_prompt('>>> ')
|
||||||
|
sys.stdout = code_out = StringIO.StringIO()
|
||||||
|
sys.stderr = code_err = StringIO.StringIO()
|
||||||
|
ok = True
|
||||||
|
try:
|
||||||
|
exec code_obj in w.mode.globals, w.mode.locals
|
||||||
|
except Exception, e:
|
||||||
|
ok = False
|
||||||
|
output = str(e) + '\n'
|
||||||
|
sys.stdout = sys.__stdout__
|
||||||
|
sys.stdout = sys.__stderr__
|
||||||
|
if ok:
|
||||||
|
output = code_out.getvalue()
|
||||||
|
code_out.close()
|
||||||
|
code_err.close()
|
||||||
|
except (SyntaxError, OverflowError, ValueError), e:
|
||||||
|
a.set_mini_buffer_prompt('>>> ')
|
||||||
|
t = sys.exc_traceback
|
||||||
|
output = str(e) + traceback.format_exc()
|
||||||
|
|
||||||
|
if output:
|
||||||
|
newlines = [' %s' % x for x in output.split('\n')]
|
||||||
|
assert newlines[-1] == ' '
|
||||||
|
newlines[-1] = ''
|
||||||
|
b.insert_lines(b.get_buffer_end(), newlines, force=True)
|
||||||
|
for w2 in b.windows:
|
||||||
|
w2.goto_end()
|
||||||
|
|
||||||
|
class ConsoleCancel(method.Method):
|
||||||
|
def execute(self, w, **vargs):
|
||||||
|
w.application.close_mini_buffer()
|
||||||
|
|
||||||
|
class ConsoleHistoryPrev(method.Method):
|
||||||
|
def execute(self, w, **vargs):
|
||||||
|
if w.mode.hindex <= 0:
|
||||||
|
w.mode.hindex = 0
|
||||||
|
return
|
||||||
|
elif w.mode.hindex == len(w.mode.history) - 1:
|
||||||
|
w.mode.history[-1] = w.buffer.make_string()
|
||||||
|
w.mode.hindex -= 1
|
||||||
|
w.buffer.set_data(w.mode.history[w.mode.hindex])
|
||||||
|
class ConsoleHistoryNext(method.Method):
|
||||||
|
def execute(self, w, **vargs):
|
||||||
|
if w.mode.hindex == len(w.mode.history) - 1:
|
||||||
|
return
|
||||||
|
w.mode.hindex += 1
|
||||||
|
w.buffer.set_data(w.mode.history[w.mode.hindex])
|
||||||
|
|
||||||
|
#class ConsoleTab(method.Method):
|
||||||
|
# def execute(self, w, **vargs):
|
||||||
|
# a = w.application
|
||||||
|
# s = w.buffer.make_string()
|
||||||
|
#
|
||||||
|
# if '"' in s or "'" in s or "(" in s or ")" in s or "[" in s or "]" in s:
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# parts = s.split(".")
|
||||||
|
# if len(parts) == 0:
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# v = a.globals()
|
||||||
|
# v.update(a.locals())
|
||||||
|
# obj = None
|
||||||
|
# for part in parts[:-1]:
|
||||||
|
# if obj is None:
|
||||||
|
# if part in v:
|
||||||
|
# obj = v[part]
|
||||||
|
# else:
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# if hasattr(obj, part):
|
||||||
|
# obj = getattr(obj, part)
|
||||||
|
# else:
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# if obj is None:
|
||||||
|
# pool = v.keys()
|
||||||
|
# else:
|
||||||
|
# pool = dir(obj)
|
||||||
|
# candidates = [x for x in pool if x.startswith(parts[-1])]
|
||||||
|
#
|
||||||
|
# if len(candidates) == 0:
|
||||||
|
# return
|
||||||
|
#
|
||||||
|
# common = completer.find_common_string(candidates)
|
||||||
|
# s2 = '.'.join(parts[:-1]) + '.' + common
|
||||||
|
#
|
||||||
|
# w.buffer.set_data(s2)
|
||||||
|
#
|
||||||
|
# if len(candidates) > 1:
|
||||||
|
# if not a.has_buffer_name('*Console*'):
|
||||||
|
# a.add_buffer(buffer.ConsoleBuffer())
|
||||||
|
# b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||||
|
# b.insert_string(b.get_buffer_end(), repr(candidates) + '\n', force=True)
|
|
@ -1,11 +1,6 @@
|
||||||
import color, method, mode2, re
|
import color, method, mode2, re
|
||||||
from lex2 import Grammar, PatternRule, RegionRule
|
from lex2 import Grammar, PatternRule, RegionRule
|
||||||
|
|
||||||
class MetadataGrammar(Grammar):
|
|
||||||
rules = [
|
|
||||||
PatternRule(name=r'line', pattern=r'^.*$'),
|
|
||||||
]
|
|
||||||
|
|
||||||
class DiffGrammar(Grammar):
|
class DiffGrammar(Grammar):
|
||||||
rules = [
|
rules = [
|
||||||
PatternRule(name=r'left', pattern=r"^\-.*$"),
|
PatternRule(name=r'left', pattern=r"^\-.*$"),
|
||||||
|
|
15
window2.py
15
window2.py
|
@ -392,7 +392,20 @@ class Window(object):
|
||||||
self.assure_visible_cursor()
|
self.assure_visible_cursor()
|
||||||
def goto_end(self):
|
def goto_end(self):
|
||||||
self.cursor = self.buffer.get_buffer_end()
|
self.cursor = self.buffer.get_buffer_end()
|
||||||
self.assure_visible_cursor()
|
(x, y) = self.logical_cursor().xy()
|
||||||
|
counter = 0
|
||||||
|
while counter < self.height - 2:
|
||||||
|
if x > self.width:
|
||||||
|
x -= self.width
|
||||||
|
elif y > 0:
|
||||||
|
y -= 1
|
||||||
|
x = len(self.buffer.lines[y])
|
||||||
|
else:
|
||||||
|
(x, y) = (0, 0)
|
||||||
|
break
|
||||||
|
counter += 1
|
||||||
|
self.first = Point(x - (x % self.width), y)
|
||||||
|
self.redraw()
|
||||||
|
|
||||||
# mark manipulation
|
# mark manipulation
|
||||||
def set_mark_point(self, p):
|
def set_mark_point(self, p):
|
||||||
|
|
Loading…
Reference in New Issue