1

The program I am working atm has a terminal-style interface. I have a block of code that checks for the input with a custom library I made :

try:
            rawcmd = typing_.typingInput('> ').split() # Splits the command into 2 parts.
            try:
                global cmd
                cmd = rawcmd[0]
            except IndexError:
                cmd = ' ' 

and then that leads into a large ladder of if elif statements (I'll only provide a few):

            if cmd == '?' or cmd =='help': # Lists out all the commands and what each one does.
     # Just some filler code here
            elif cmd == 'ls': # Lists out the Current Working Directory, aswell as all the files within that directory.
                typing_.typingPrint('Current Working Directory: ' +os.getcwd()+'\n')
                delimiter = '\n'
                files = delimiter.join(os.listdir())
                typing_.typingPrint(files+'\n')
            elif cmd == 'cd': # Changes the directory to the supplied one
                try:
                    path = os.path.abspath(rawcmd[1])
                    os.chdir(path)
                except FileNotFoundError:
                    typing_.typingPrint('No Directory with that name')
            elif cmd == 'mkdir': # Creates a new Folder in the file system.
                name=rawcmd[1]
                os.mkdir(name)
            elif cmd == 'mkfile': # Runs the CreateFile() function
                name = rawcmd[1]
                createFile(name)
            elif cmd == 'rmvfile': # Runs the DeleteFile() function
                name = rawcmd[1]
                deleteFile(name)
            elif cmd == 'editfile': # Runs the EditFile() function
                name = rawcmd[1]
                editFile(name)
            elif cmd == 'readfile': # Runs the ReadFile() function
                name = rawcmd[1]
                viewFile(name)
            elif cmd == 'rmvtree': # Deletes the supplied folder and all files within.
                name = rawcmd[1]
                shutil.rmtree(name)
            elif cmd == 'exit': # Quits the Terminal.

Is there a better way to do this that would be more efficient, and easier for other people to read?

001
  • 13,291
  • 5
  • 35
  • 66
Jaxer5636
  • 97
  • 10
  • 3
    A dictionary where the key is the command text and the value is the exec: `commands = {"mkdir": os.mkdir, "mkfile": createFile....}`. Usage would be `if cmd in command: commands[cmd](name)`. You might have to add some more stuff to handle different numbers of parameters, etc. – 001 May 14 '23 at 14:19

1 Answers1

4

First make sure that each menu command can be represented as a function, so you don't need blocks of implementation inside the code that handles your menu:

def cmd_help():
    # just some filler code here
    pass

def ls():
    typing_.typingPrint('Current Working Directory: ' +os.getcwd()+'\n')
    delimiter = '\n'
    files = delimiter.join(os.listdir())
    typing_.typingPrint(files+'\n')

def cd(name):
    try:
        path = os.path.abspath(name)
        os.chdir(path)
    except FileNotFoundError:
        typing_.typingPrint('No Directory with that name')

Now you can build a dict of command names to functions:

cmd_funcs = {
    '?': cmd_help,
    'help': cmd_help,
    'ls': ls,
    'cd': cd,
    'mkdir': os.mkdir,
    'mkfile': createFile,
    'rmvfile': deleteFile,
    'editFile': editFile,
    'readfile': viewFile,
    'rmvtree': shutil.rmtree,
    'exit': exit,
}

and implement your menu as:

if rawcmd[0] in cmd_funcs:
    cmd_funcs[rawcmd[0]](*rawcmd[1:])

or perhaps something like:

try:
    cmd_funcs[rawcmd[0]](*rawcmd[1:])
except KeyError:
    print("Invalid command:", rawcmd[0])
except TypeError:
    print("Invalid command arguments:", *rawcmd[1:])
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • So, does that mean its possible to have a command run if its set as a value and the key is called somewhere else in the program? – Jaxer5636 May 14 '23 at 16:03
  • I'm not sure exactly what you're asking, but yes, you should be able to call parts of your program from other parts of your program, in general. – Samwise May 14 '23 at 16:06
  • How would I go about assigning the arguments to the functions with this method? (ex. createFile notes.txt) – Jaxer5636 May 14 '23 at 17:12
  • The code in my answer does that for you. The `*` operator spreads the elements of `rawcmd[1:]` (which is a list slice) to become the args of the function. If the number of elements in the list doesn't match the number of args expected by the function, Python will raise a `TypeError`. – Samwise May 14 '23 at 17:21
  • Ok, that makes sense. So in my createFile function, it should just immediately pass the notes.txt into the fileName argument? – Jaxer5636 May 14 '23 at 17:33
  • If `rawcmd[1]` is `"notes.txt"`, then yes, that is what will happen. – Samwise May 14 '23 at 17:46