omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Ui code editor questions

    Pythonista
    2
    6
    1852
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • rb
      rb last edited by

      Hi is it possible to display matching paired brackets /curly braces etc? I’m sure this used to be the case.ie if you had a JSON file and selected a curly brace it matching brace would be highlighted /selected in correct location.

      Is it possible to change the extra keyboard shortcuts above main virtual keyboard to appear as one large spaced line of options rather than two v small menus on the left and right? Is this an option as again I’m sure it didn’t used to look like this.

      Cheers
      Rich

      cvp 4 Replies Last reply Reply Quote 0
      • cvp
        cvp @rb last edited by

        @rb said:

        Is it possible to change the extra keyboard shortcuts above main virtual keyboard to appear as one large spaced line of options rather than two v small menus on the left and right?

        If it is what I understand, like here, it seems to be a bug

        1 Reply Last reply Reply Quote 0
        • cvp
          cvp @rb last edited by

          @rb it is possible via a script defined as a Pythonista tool, adding an additional key in Pythonista keyboard.
          Example here-under only shows how to find next ending character, not really the matching pair, but this script only to show the way.

          Put your cusor on a ( or [ or {, tap the "pair" button

          and you will get this

          To erase special backgrounds, tap pair with cursor on any other character

          import editor
          from   objc_util import *
          import ui
          
          def key_pressed(sender):
          		import ui
          		from objc_util import ObjCClass
          		tv = sender.objc_instance.firstResponder()	# associated TextView
          		# get actual cursor position					
          		cursor = tv.offsetFromPosition_toPosition_(tv.beginningOfDocument(), tv.selectedTextRange().start())
          		
          		if sender.name == 'pair':
          			for sv in tv.subviews():
          				if 'SUIButton_PY3' in str(sv._get_objc_classname()):
          					sv.removeFromSuperview()
          
          			pairs = {'(':')','[':']','{':'}'}
          			t = str(tv.text())[cursor]	
          			if t not in pairs:
          				return
          			ts = pairs[t]
          			t = str(tv.text())[cursor+1:]
          			cursor += 1
          			while True:	
          				try:
          					t = str(tv.text())[cursor]	
          				except:
          					return
          				if t == ts:
          					p1 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor)
          					p2 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor+1)
          					rge = tv.textRangeFromPosition_toPosition_(p1,p2)
          					rect = tv.firstRectForRange_(rge)	# CGRect
          					x,y = rect.origin.x,rect.origin.y
          					w,h = rect.size.width,rect.size.height
          					l = ui.Button()
          					l.frame = (x,y,w,h)
          					l.background_color = (1,0,0,0.2)
          					l.corner_radius = 4
          					l.border_width = 1
          					tv.addSubview_(l)
          					break
          				cursor += 1
          		else:
          			# normal key
          			tv.insertText_(sender.title)	
          			return
          		# set cursor
          		cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor)
          		tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position)	
          
          class MyView(ui.View):
          	def __init__(self, pad, *args, **kwargs):
          		#super().__init__(self, *args, **kwargs)	
          		self.width = ui.get_screen_size()[0]			# width of keyboard = screen
          		self.background_color = 'lightgray'#(0,1,0,0.2)
          		self.h_button = 32	
          		self.pad = pad
          		
          		# build buttons
          		for pad_elem in self.pad:
          			if pad_elem['key'] in ('nul', 'new row'):		#  free space or new row
          				continue
          			button = ui.Button()									# Button for user functionnality
          			button.name = pad_elem['key']
          			button.background_color = 'white'			# or any other color
          			button.tint_color = 'black'
          			button.corner_radius = 5		
          			button.font = ('<system>',self.h_button - 8)
          			button.title = ''
          			if 'title' in pad_elem:
          				button.title = pad_elem['title']
          			elif 'icon' in pad_elem:
          				button.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
          			else:
          				button.title = pad_elem['key']
          
          			button.action = key_pressed
          			retain_global(button) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
          			self.add_subview(button)	
          		self.layout()		
          
          	def layout(self):
          		import ui
          		#print('layout')
          		# supports changing orientation
          		#print(ui.get_screen_size())
          		dx = 8
          		dy = 2
          		x0 = 15
          		y0 = 10
          		dx_middle = 25 
          		y = y0
          		x = x0
          		w_button = (ui.get_screen_size()[0] - 2*x0 - 17*dx - dx_middle)/18
          		for pad_elem in self.pad:
          			nw = pad_elem.get('width', 1)
          			wb = w_button*nw + dx*(nw-1)
          			if (x + wb + dx) > self.width:
          				y = y + self.h_button + dy
          				x = x0
          			if pad_elem['key'] == 'nul':					# let free space	
          				x = x + wb + dx	
          				continue
          			elif pad_elem['key'] == 'new row':		# new row
          				y = y + self.h_button + dy
          				x = x0
          				continue
          			button = self[pad_elem['key']]
          			xb = x + dx_middle if (x+wb) > self.width/2 else x
          			button.frame = (xb,y,wb,self.h_button)
          			if button.title != '':
          				font_size = self.h_button - 8
          				while True:
          					d = ui.measure_string(button.title,font=(button.font[0],font_size))[0]+4
          					if d <= wb:
          						break
          					font_size = font_size - 1			
          			button.font = (button.font[0],font_size)
          			x = x + wb + dx
          		self.height = y + self.h_button + dy	
          	
          @on_main_thread	
          def AddButtonsToPythonistaKeyboard(pad=None):
          	ev = editor._get_editor_tab().editorView()
          	tv = ev.textView()
          	#print(tv._get_objc_classname())
          	#print(dir(tv))
          	
          	# create ui.View for InputAccessoryView above keyboard
          	v = MyView(pad)												# view above keyboard
          	vo = ObjCInstance(v)									# get ObjectiveC object of v
          	retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
          	tv.setInputAccessoryView_(vo)	# attach accessory to textview
          	tv.strfind = ''
          
          if __name__ == '__main__':	
          	AddButtonsToPythonistaKeyboard(pad=[{'key':'pair'}])
          
          1 Reply Last reply Reply Quote 0
          • cvp
            cvp @rb last edited by

            @rb I'm sure we could do the same via an user menu, like

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @rb last edited by

              @rb real pairing

              With

              import editor
              from   objc_util import *
              import ui
              
              def key_pressed(sender):
              		import ui
              		from objc_util import ObjCClass
              		tv = sender.objc_instance.firstResponder()	# associated TextView
              		# get actual cursor position					
              		cursor = tv.offsetFromPosition_toPosition_(tv.beginningOfDocument(), tv.selectedTextRange().start())
              		
              		if sender.name == 'pair':
              			for sv in tv.subviews():
              				if 'SUIButton_PY3' in str(sv._get_objc_classname()):
              					sv.removeFromSuperview()
              
              			pairs = {'(':')','[':']','{':'}'}
              			t = str(tv.text())[cursor]	
              			if t not in pairs:
              				return
              			cursors = [cursor]
              			ts = pairs[t]
              			#tc = str(tv.text())[cursor+1:]
              			cursor += 1
              			n = 0
              			while True:	
              				try:
              					tc = str(tv.text())[cursor]	
              				except:
              					return
              				if tc == t:
              					n = n + 1
              				elif tc == ts:
              					if n == 0:	
              						cursors.append(cursor)
              						for cursor in cursors:
              							p1 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor)
              							p2 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor+1)
              							rge = tv.textRangeFromPosition_toPosition_(p1,p2)
              							rect = tv.firstRectForRange_(rge)	# CGRect
              							x,y = rect.origin.x,rect.origin.y
              							w,h = rect.size.width,rect.size.height
              							l = ui.Button()
              							l.frame = (x,y,w,h)
              							l.background_color = (1,0,0,0.2)
              							l.corner_radius = 4
              							l.border_width = 1
              							tv.addSubview_(l)
              						break
              					n = n - 1
              				cursor += 1
              		else:
              			# normal key
              			tv.insertText_(sender.title)	
              			return
              		# set cursor
              		cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor)
              		tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position)	
              
              class MyView(ui.View):
              	def __init__(self, pad, *args, **kwargs):
              		#super().__init__(self, *args, **kwargs)	
              		self.width = ui.get_screen_size()[0]			# width of keyboard = screen
              		self.background_color = 'lightgray'#(0,1,0,0.2)
              		self.h_button = 32	
              		self.pad = pad
              		
              		# build buttons
              		for pad_elem in self.pad:
              			if pad_elem['key'] in ('nul', 'new row'):		#  free space or new row
              				continue
              			button = ui.Button()									# Button for user functionnality
              			button.name = pad_elem['key']
              			button.background_color = 'white'			# or any other color
              			button.tint_color = 'black'
              			button.corner_radius = 5		
              			button.font = ('<system>',self.h_button - 8)
              			button.title = ''
              			if 'title' in pad_elem:
              				button.title = pad_elem['title']
              			elif 'icon' in pad_elem:
              				button.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
              			else:
              				button.title = pad_elem['key']
              
              			button.action = key_pressed
              			retain_global(button) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
              			self.add_subview(button)	
              		self.layout()		
              
              	def layout(self):
              		import ui
              		#print('layout')
              		# supports changing orientation
              		#print(ui.get_screen_size())
              		dx = 8
              		dy = 2
              		x0 = 15
              		y0 = 10
              		dx_middle = 25 
              		y = y0
              		x = x0
              		w_button = (ui.get_screen_size()[0] - 2*x0 - 17*dx - dx_middle)/18
              		for pad_elem in self.pad:
              			nw = pad_elem.get('width', 1)
              			wb = w_button*nw + dx*(nw-1)
              			if (x + wb + dx) > self.width:
              				y = y + self.h_button + dy
              				x = x0
              			if pad_elem['key'] == 'nul':					# let free space	
              				x = x + wb + dx	
              				continue
              			elif pad_elem['key'] == 'new row':		# new row
              				y = y + self.h_button + dy
              				x = x0
              				continue
              			button = self[pad_elem['key']]
              			xb = x + dx_middle if (x+wb) > self.width/2 else x
              			button.frame = (xb,y,wb,self.h_button)
              			if button.title != '':
              				font_size = self.h_button - 8
              				while True:
              					d = ui.measure_string(button.title,font=(button.font[0],font_size))[0]+4
              					if d <= wb:
              						break
              					font_size = font_size - 1			
              			button.font = (button.font[0],font_size)
              			x = x + wb + dx
              		self.height = y + self.h_button + dy	
              	
              @on_main_thread	
              def AddButtonsToPythonistaKeyboard(pad=None):
              	ev = editor._get_editor_tab().editorView()
              	tv = ev.textView()
              	#print(tv._get_objc_classname())
              	#print(dir(tv))
              	
              	# create ui.View for InputAccessoryView above keyboard
              	v = MyView(pad)												# view above keyboard
              	vo = ObjCInstance(v)									# get ObjectiveC object of v
              	retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
              	tv.setInputAccessoryView_(vo)	# attach accessory to textview
              	tv.strfind = ''
              
              if __name__ == '__main__':	
              	AddButtonsToPythonistaKeyboard(pad=[{'key':'pair'}])
              
              1 Reply Last reply Reply Quote 0
              • rb
                rb last edited by

                Wow above and beyond the call of duty thankyou!

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors