Sometimes it's fun to see how an idea translates when coded in several languages. In this article, the central idea is having a table that maps a command name to a function. A runloop prompts the user for a command, looks up the command in the table, and, if it exists, executes the associated function. The python cmd module is a take on this idea. Here we code up something much more rudimentary in python, ruby, and lua.
cmd.py
!/usr/bin/env python import sys def connect(host): print('connecting to %s...' % (host)) def download(path): print('downloading %s...' % (path)) def upload(path): print('uploading %s...' % (path)) def disconnect(): print ('disconnecting...') sys.exit(0) commands = { 'connect': connect, 'download': download, 'upload': upload, 'disconnect' : disconnect } while True: line = raw_input('% ') tokens = line.split() if not tokens: continue cmd = tokens[0] args = tokens[1:] if cmd in commands: try: commands[cmd](*args) except TypeError as e: print(e) else: print("cmd '%s' not found" % (cmd))
cmd.rb
!/usr/bin/env ruby def connect(host) puts "connecting to #{host}..." end def download(path) puts "downloading #{path}..." end def upload(path) puts "uploading #{path}..." end def disconnect() puts "disconnecting..." exit end commands = { 'connect' => :connect, 'download' => :download, 'upload' => :upload, 'disconnect' => :disconnect, } while true do print '% ' tokens = gets.split cmd = tokens[0] args = tokens[1..-1] if cmd and commands[cmd] then begin send(commands[cmd], *args) rescue ArgumentError => e puts e.message end else puts "cmd '#{cmd}' not found" end end
cmd.lua
#!/usr/bin/env lua --------------------------------------- -- utility functions --------------------------------------- local function split(s) local tokens = {} for t in string.gmatch(s, "%S+") do --print('token: ' .. t) tokens[#tokens + 1] = t end return tokens end local function printf(fmt, ...) if fmt then return io.write(string.format(fmt, ...)) else return print() end end local function perror(msg) -- strip file and line number where error occurs local i, j = string.find(msg, ':%d+:%s+') if j then print(string.sub(msg, j+1, -1)) else print(msg) end end --------------------------------------- -- commands --------------------------------------- local function connect(host) if not host then error('must specify host') end printf('connecting to %s...\n', host) end local function download(path) if not path then error('must specify path') end printf('downloading %s...\n', path) end local function upload(path) if not path then error('must specify path') end printf('uploading %s..\n', path) end local function disconnect() printf('disconnecting...\n') os.exit(0) end --------------------------------------- -- command table --------------------------------------- local commands = { connect = connect, upload = upload, download = download, disconnect = disconnect } --------------------------------------- -- runloop --------------------------------------- while true do io.write('% ') io.flush() local line = io.read('*line') local tokens = split(line) if #tokens > 0 then local cmd = tokens[1] table.remove(tokens, 1) local args = tokens if commands[cmd] then local status, err = pcall(commands[cmd], unpack(args)) if not status then perror(err) end else printf("cmd '%s' not found\n", cmd) end end end