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