Question

So I'm writing a shell in Python, and the filename is jsh.py. When I run the code, it doesn't work for some reason. A window pops up but closes immediately. What is worng with my code?

import os
import random
import time
import path
import string
import sys

commandAvail = 'ls where chdir mk mkdir cp mv rm rmdir view ext shutdown edit unix dos man-all man-unix man-dos'
commandAvailUnix = 'exec permission group'
commandAvailDos = ' '
print('Welcome to jsh alpha 1!')
commandPlatform = input('System: (UNIX/DOS):')
commandLine()

def commandLine():
        while 1 == 1:
                command = input('$ ')
                if command in commandAvail:
                        if command.startswith('ls'):
                                commandKeyword = 'ls'
                                commandOptions = command - commandKeyword
                                ls(commandOptions)
                        elif command.startswith('where'):
                                commandKeyword = 'where'
                                commandOptions = command - commandKeyword
                                where()
                        elif command.startswith('chdir'):
                                commandKeyword = 'chdir'
                                commandOptions = command - commandKeyword
                                chdir()
                        elif command.startswith('mk'):
                                commandKeyword = 'mk'
                                commandOptions = command - commandKeyword
                                mk()
                        elif command.startswith('mkdir'):
                                commandKeyword = 'mkdir'
                                commandOptions = command - commandKeyword
                                mkdir()
                        elif command.startswith('cp'):
                                commandKeyword = 'cp'
                                commandOptions = command - commandKeyword
                                cp()
                        elif command.startswith('mv'):
                                commandKeyword = 'mv'
                                commandOptions = command - commandKeyword
                                mv()
                        elif command.startswith('rm'):
                                commandKeyword = 'rm'
                                commandOptions = command - commandKeyword
                                rm()
                        elif command.startswith('rmdir'):
                                commandKeyword = 'rmdir'
                                commandOptions = command - commandKeyword
                                rm()
                        elif command.startswith('view'):
                                commandKeyword = 'view'
                                commandOptions = command - commandKeyword
                                rm()
                        elif command.startswith('edit'):
                                commandKeyword = 'edit'
                                commandOptions = command - commandKeyword
                                edit()
                        elif command == 'man-all':
                                print('Commands that work for all underlying platforms:')
                                print(commandAvail)
                        elif command == 'man-unix':
                                print('Commands that only work on Unix systems:')
                                print(commandAvailUnix)
                        elif command == 'man-dos'
                                print('Commands that only work on DOS systems:')
                                print(commandAvailDos)
                        elif command.startswith('unix'):
                                commandType = 'unix'
                                unix()
                        elif command.startswith('dos'):
                                commandType = 'dos'
                                dos()
                        elif command.startswith('ext'):
                                commandKeyword = 'ext'
                                commandOptions = command - commandKeyword
                                ext()
                        elif command == 'shutdown':
                                sys.quit(0)
                        else:
                                print('jsh has experienced an internal error and has to shutdown.')
                                sys.quit(10)
                else:
                        print('Command \'' + command + '\' not recognized as internal or external.')

def ls(options):
        if commandPlatform == 'UNIX':
                os.system('ls' + options)
        else:
                os.system('dir' + options)
        commandLine()
Was it helpful?

Solution

You forgot to put ':' after elif command == 'man-dos'

Just run: python3 yourscript for debugging purposes.

OTHER TIPS

There are several errors in your current code:

  1. First, you have some messed up indentation, including a mixture of tabs and spaces used for indentation. This is very bad in Python, as incorrect indentation is a syntax error. I've fixed the code in the question to appear correctly (using 8 spaces per tab) but you will need to fix it in your file too. Also, be aware that the Python convention is to indent by four spaces per block, so you may want to set your editor to do that by default.

  2. Second, the logic for your top level check is incorrect. You're testing if the whole command string is contained with the string of commands you have in the commandAvail variable. This will do the wrong thing if the command has arguments in addition to a command name. What I suggest is that you split the command string to get a list of terms, then only test the first term against the available commands. And rather than doing a substring search, I suggest splitting commandAvail into a set of strings:

    # make a set of commands that we recognize
    commandAvail = set('ls where chdir mk mkdir cp'.split()) # trimmed for space
    
    # then later, test against it
    command = input().split()
    if command[0] in commandAvail: # this is much more efficient!
        # do stuff
    
  3. Lastly, the way you're trying to remove the command itself from the command string is wrong. You can't subtract a string from another string (you'll get a TypeError if you try). Fortunately, the solution I suggested for the previous issue will help here. Instead of doing string manipulation, you will have a list of terms, thanks to the split call. Now, you just test against the first item (the command), and pass the rest as arguments.

    In fact, this suggests a much simpler implementation than the big chain of if/elif blocks you currently have. Use a dictionary to map between command strings and the functions that implement them:

    # map command names to the functions that implement them
    command_dict = {"ls":ls, "where":where, "chdir":chdir} # snipped
    
    # the main loop
    while True:
        # command is first term, the rest go into args
        command, *args = input().split()
    
        try: # use "easier to ask forgiveness than permission" idiom
            command_dict[command](*args) # call function from command_dict
        except KeyError:
            print("Unknown command: {}".format(command))
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top