Search code examples
pythonkivyrestructuredtexttextinput

Kivy: TextInput selection_text issue


Here is a code for simple rst editor copied from here, In this code selection_text is surrounded by desired tags, but here is an issue i can select text only from left to right, when text is selected from right to left it doesn't work as before, is there any possibility to select from any side like other text editors?

from kivy.app import App
from kivy.base import Builder
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout



Builder.load_string("""
<root_wgt>:
    orientation: 'vertical'
    BoxLayout:
        size_hint_y:0.2
        Button:
            text: 'Emphasize'
            on_press: root.emphasize()
        Button:
            text: 'Section Header'
            on_press: root.add_section_header()
        Button:
            text: 'Subection Header'
            on_press: root.add_sub_section_header()

    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: textinput

        RstDocument:
            id: rstdocument
            text: textinput.text
""")


class root_wgt(BoxLayout):
    def emphasize(self):
        text = self.ids.textinput.text
        selection = self.ids.textinput.selection_text
        begin = self.ids.textinput.selection_from
        end = self.ids.textinput.selection_to
        new_text = text[:begin] + ' **' + selection + '** ' + text[end:]
        self.ids.textinput.text = new_text
        self.ids.rstdocument.render()

    def add_section_header(self):
        self.ids.textinput.insert_text("""\n==============""")

    def add_sub_section_header(self):
        self.ids.textinput.insert_text("""\n-----------------""")

class MyApp(App):
    def build(self):
        return root_wgt()

if __name__ == '__main__':
    MyApp().run()

Solution

  • The problem is caused because when you select from right to left the selection_to is greater than selection_from so the extraction of data causes duplicate elements causing this inappropriate behavior, the solution is that begin and end are correctly ordered for it we use sorted:

    def emphasize(self):
        text = self.ids.textinput.text
        selection = self.ids.textinput.selection_text
        begin, end = sorted([self.ids.textinput.selection_from, self.ids.textinput.selection_to])
        new_text = text[:begin] + ' **' + selection + '** ' + text[end:]
        self.ids.textinput.text = new_text
        self.ids.rstdocument.render()