Search code examples
pythoncommand-linecommandkivytextinput

Making a command line with KIvy


I have been trying to simulate a command line design which would allow me to:
- Type in a command
- Execute it
- Output it in the same window below the command text that I have typed in.
So what I need is this:

command_one
command one has been processed and this is the output

I have partially completed this but what happens is that the output text overwrites the input instead of 'adding up'. Another problem that I have encountered is that I have to click on the TextInput window every time I need to type something in instead of just being able to keep typing in the commands without ever using my mouse.

Is there any workaround that will help me solve this?

Here is my code: (mainapp.py)(changed)

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MainWindow(BoxLayout):
    # We create a dictionary of all our possible methods to call, along with keys
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs) #This makes sure the kivy super classes from which MainWindow descends get initialized correctly.

        self.command_dict =  {
            'one': self.command_one,
            'two': self.command_two,
            'three': self.command_three,
        }
    def process_command(self):
        # We grab the text from the user text input as a key
        command_key = self.ids.fetch_key_and_process_command.text
        old_text = command_key.strip()

        # We then use that key in the command's built in 'get_method' because it is a dict
        # then we store it into a variable for later use
        called_command = self.command_dict().get[old_text, 'default']
        try:
            # The variable is a method, so by adding we can call it by simple adding your typical () to the end of it.
            called_command()

        except TypeError:
            # However we use an exception clause to catch in case people enter a key that doesn't exist
            self.ids.fetch_key_and_process_command.text = 'Sorry, there is no command key: ' + command_key
    # These are the three commands we call from our command dict.
    def command_one(self):
        self.ids.fetch_key_and_process_command.text = "{}\n{}\n".format(old_text, "Command One has Been Processed")

    def command_two(self):
        self.ids.fetch_key_and_process_command.text = 'Command Two has Been Processed'

    def command_three(self):
        self.ids.fetch_key_and_process_command.text = 'Command Three has been Processed'



class MainApp(App):

    def build(self):
        return MainWindow()

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

(mainapp.kv)

<MainWindow>:
    Label:
        text: 'This is a label'
    TextInput:
        id: fetch_key_and_process_command
        multiline: True  
    Button:
        id: process_command_button
        text: "Process Command"
        on_release: root.process_command()

The error that comes up says:

line 21, in process_command called_command = self.command_dict().get[command_key, 'default'] TypeError: 'dict' object is not callable


Solution

  • See this example:

    class Dog:
        def __init__(self):
            self.command_dict = {
                    'a': 1,
                    'b': 2,
            }
    
        def bark(self):
            val = self.command_dict['a']
            print(val) #=> 1
            val = self.command_dict.get('c', "hello")
            print(val) #=> hello
    
            self.command_dict['c'] = 3
            val = self.command_dict.get('c', "goodbye")
            print(val)  #=> 3
    
    
        def run(self):
            print(self.command_dict['c'])  #=>3
            print(self.I_cant_spell_command_dict_correctly['a'])  #=> error
    
    
    
    d = Dog()
    d.bark()
    d.run()
    

    Output:

    1
    hello
    3
    3
    
    Traceback (most recent call last):
      File "1.py", line 27, in <module>
        d.run()
      File "1.py", line 21, in run
        print(self.I_cant_spell_command_dict_correctly['a'])
    AttributeError: 'Dog' object has no attribute 'I_cant_spell_command_dict_correctly'
    

    If I needed to write self.command_dict more than once in a method, then I would do this:

    cmd_dict = self.command_dict
    

    and I would use cmd_dict thereafter.

    Just so you know, kivy is for intermediate to advanced python programmers. Trying to figure out the fundamentals of python in a complex setting like gui programming is going to be very frustrating.

    Response to comment:

    I thought we agreed:

    Yes, you can't write some_dict() because a dictionary is not a function.

    After you attach the dictionary to self inside __init__(), how do you retrieve the dictionary in some other method?

    Answer: self.command_dict

    Because self seems to confuse you, when you need to retrieve the dict just do this in your code:

    my_command_dict = self.command_dict
    

    Next, how do you retrieve the values in the dictionary my_command_dict? Do you write:

    val = my_command_dict()
    

    or

    val = my_command_dict['some key']
    

    ??

    And if you want to get a default value back if the key doesn't exist--instead of causing an error--and therefore you decide to use the get() method for dictionaries, do you write:

    my_command_dict.get['some key', 'default']
    

    or

    my_command_dict.get('some key', 'default')
    

    ??

    Take a look a close look at my example code and your code:

    you: called_command = self.command_dict().get[old_text, 'default']
     me:            val = self.command_dict.get('c', "hello")
    

    Can you discern any difference in your syntax and my syntax? Start at the equals sign and move to the right comparing each line character by character.