Jam/command_prompt.py

173 lines
5.3 KiB
Python
Raw Normal View History

2021-10-02 21:38:26 +00:00
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.graphics import Color,Rectangle
2021-10-02 21:38:26 +00:00
class Command_prompt(Label):
def __init__(self,app,**kwargs):
# app is used to share information between widgets
self.app=app
# insert mode
self.insert=False
# cursor position
self.cursor=0
self.cursor_width=9
# the text, with no color information
self.raw_text=""
2021-10-15 23:36:29 +00:00
# array of command with arguments
self.argv=[]
2021-10-02 21:38:26 +00:00
# init Label
super(Command_prompt,self).__init__(**kwargs)
self.keyboard = Window.request_keyboard(None,self,"text")
self.keyboard.bind(on_textinput=self.on_textinput,on_key_down=self.on_key_down)
self.draw()
def draw(self):
with self.canvas.before:
# background
Color(0,0,0)
Rectangle(pos=self.pos,size=self.size)
# cursor
Color(1,1,1)
Rectangle(pos=(self.pos[0]+self.cursor*self.cursor_width,self.pos[1]),size=(self.cursor_width,self.height))
# make text under cursor black
if self.cursor<len(self.raw_text):
self.text=self.raw_text[:self.cursor]+"[color=000]"+self.raw_text[self.cursor]+"[/color]"+self.raw_text[self.cursor+1:]
else:
self.text=self.raw_text
2021-10-02 21:38:26 +00:00
def on_key_down(self, keyboard, keycode, text, modifiers):
2021-10-15 23:57:03 +00:00
print(keycode,text,modifiers)
2021-10-02 21:38:26 +00:00
if self.insert:
2021-10-15 23:57:03 +00:00
# process command
2021-10-02 21:38:26 +00:00
if keycode[1]=="enter":
self.insert=False
2021-10-15 23:36:29 +00:00
self.parse_command()
self.set_text("")
2021-10-15 23:57:03 +00:00
# move
elif keycode[1]=="left":
2021-10-09 20:43:46 +00:00
self.move_cursor_relative(-1)
elif keycode[1]=="right":
2021-10-09 20:43:46 +00:00
self.move_cursor_relative(1)
elif len(modifiers)==1 and modifiers[0]=="ctrl" and text=="a":
self.move_cursor(1)
2021-10-09 20:43:46 +00:00
elif len(modifiers)==1 and modifiers[0]=="ctrl" and text=="e":
self.move_cursor(len(self.raw_text))
2021-10-02 21:38:26 +00:00
2021-10-15 23:57:03 +00:00
# delete
elif keycode[1]=="backspace":
self.backspace()
elif keycode[1]=="delete":
self.delete_forward()
elif len(modifiers)==1 and modifiers[0]=="ctrl" and text=="k":
self.delete_all_forward()
2021-10-02 21:38:26 +00:00
def on_textinput(self,window,text):
2021-10-15 23:36:29 +00:00
#print(text)
2021-10-02 21:38:26 +00:00
if self.insert:
self.append_text_at_cursor(text)
2021-10-02 21:38:26 +00:00
elif text==':':
self.append_text_at_cursor(text)
2021-10-02 21:38:26 +00:00
self.insert=True
# append to text at position of cursor
def append_text_at_cursor(self,text):
if self.cursor==len(self.raw_text):
self.raw_text+=text
else:
self.raw_text=self.raw_text[:self.cursor]+text+self.raw_text[self.cursor:]
self.cursor+=len(text)
self.draw()
2021-10-15 23:57:03 +00:00
# delete before cursor
def backspace(self):
# do not delete leading ':'
if self.cursor==1:
return
if self.cursor==len(self.raw_text):
self.raw_text=self.raw_text[:self.cursor-1]
else:
self.raw_text=self.raw_text[:self.cursor-1]+self.raw_text[self.cursor:]
self.cursor-=1
self.draw()
# delete after cursor
def delete_forward(self):
if self.cursor==len(self.raw_text):
return
else:
self.raw_text=self.raw_text[:self.cursor]+self.raw_text[self.cursor+1:]
self.draw()
# delete until end of line(self):
def delete_all_forward(self):
if self.cursor==len(self.raw_text):
return
else:
self.raw_text=self.raw_text[:self.cursor]
self.draw()
# set text in prompt
def set_text(self,text):
self.raw_text=text
self.cursor=len(text)
self.draw()
# move cursor n steps to right (left if negative)
2021-10-09 20:43:46 +00:00
def move_cursor_relative(self,n):
if n==0 or (n>0 and self.cursor==len(self.raw_text)) or (n<0 and self.cursor==0):
return
2021-10-09 20:43:46 +00:00
self.cursor=max(1,min(len(self.raw_text),self.cursor+n))
self.draw()
# move cursor to absolute position
def move_cursor(self,n):
self.cursor=max(1,min(len(self.raw_text),n))
self.draw()
2021-10-15 23:36:29 +00:00
# parse text as argv
def parse_command(self):
# init
self.argv=[""]
# whether inside quotes
single_quoted=False
double_quoted=False
# whether after '\'
backslashed=False
# start after ':'
# proceed one character at a time
for i in range(1,len(self.raw_text)):
char=self.raw_text[i]
# split argument
if single_quoted==False and double_quoted==False and backslashed==False and char==' ':
# new argv
self.argv.append("")
# quotes or '\'
elif double_quoted==False and backslashed==False and char=='\'':
single_quoted=not single_quoted
elif single_quoted==False and backslashed==False and char=='"':
double_quoted=not double_quoted
elif single_quoted==False and backslashed==False and char=='\\':
backslashed=True
# write character
else:
self.argv[len(self.argv)-1]+=char
# reset backslash
backslashed=False