from kivy.uix.label import Label from kivy.core.window import Window from kivy.graphics import Color,Rectangle import glob import os.path from tools import common_substr 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 # width of a letter self.char_width=9 # cursor position self.cursor=0 # the text, with no color information self.raw_text="" # array of command with arguments self.argv=[] # display characters from window_offset onwards (for text wrapping) self.window_offset=0 # 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): # wrap text window_size=int(self.width/self.char_width) if self.cursor>=self.window_offset+window_size: self.window_offset=self.cursor-window_size+1 elif self.cursor0 and self.cursor==len(self.raw_text)) or (n<0 and self.cursor==0): return 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() # parse text as argv def parse_argv(self): # init self.argv=[""] # return position of cursor cursor=(0,0) # 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 # record position of cursor if self.cursor==i+1: cursor=(len(self.argv)-1,len(self.argv[len(self.argv)-1])) return cursor # tab completion def tab_complete(self): # parse argv cursor=self.parse_argv() # write and edit commands if self.argv[0]=="w" or self.argv[0]=="e": # check that cursor is in first argument if cursor[0]==1: # complete filesystem path self.append_text_at_cursor(self.complete_path(self.argv[1],cursor[1])) # complete filesystem path def complete_path(self,base,end): paths=glob.glob(glob.escape(base[:end])+"*") print(glob.escape(base[:end])+"*", paths) if len(paths)==0: return "" elif len(paths)==1: # append '/' to directories if os.path.isdir(paths[0]): return paths[0][end:]+"/" else: return paths[0][end:] else: # display in status bar self.app.status_bar.raw_text="" for path in paths: name=os.path.basename(path) # add quotes if needed if " " in name: name="\""+name+"\"" self.app.status_bar.raw_text+=name+" " self.app.status_bar.draw() return common_substr(paths)[end:]