This repository has been archived by the owner on Dec 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
shell.py
197 lines (156 loc) · 5.96 KB
/
shell.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#
# Licensed under the GNU General Public License Version 3
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright 2012 James Tanner <tanner.jc@gmail.com>
#
# NOTE: the 'self' variable is an instance of RpathShell
import atexit, logging, os, readline, re, sys
from cmd import Cmd
from pwd import getpwuid
from rpathcmd.utils import *
import pdb
class RpathShell(Cmd):
__module_list = [ 'api', 'projects', 'groups', 'systems', 'images', 'platforms', 'targets', 'packages']
# a SyntaxError is thrown if we don't wrap this in an 'exec'
for module in __module_list:
exec 'from %s import *' % module
# maximum length of history file
HISTORY_LENGTH = 1024
cmdqueue = []
completekey = 'tab'
stdout = sys.stdout
#prompt_template = 'rpathcmd {SSM:##}> '
prompt_template = 'rpathcmd> '
current_line = ''
# do nothing on an empty line
emptyline = lambda self: None
def __init__(self, options):
self.session = ''
self.username = ''
self.server = ''
self.ssm = {}
self.postcmd(False, '')
# make the options available everywhere
self.options = options
#pdb.set_trace()
userinfo = getpwuid(os.getuid())
self.conf_dir = os.path.join(userinfo[5], '.spacecmd')
try:
if not os.path.isdir(self.conf_dir):
os.mkdir(self.conf_dir, 0700)
except OSError:
logging.error('Could not create directory %s' % self.conf_dir)
self.history_file = os.path.join(self.conf_dir, 'history')
try:
# don't split on hyphens or colons during tab completion
newdelims = readline.get_completer_delims()
newdelims = re.sub(':|-|/', '', newdelims)
readline.set_completer_delims(newdelims)
if not options.nohistory:
try:
if os.path.isfile(self.history_file):
readline.read_history_file(self.history_file)
readline.set_history_length(self.HISTORY_LENGTH)
# always write the history file on exit
atexit.register(readline.write_history_file,
self.history_file)
except IOError:
logging.error('Could not read history file')
except:
pass
# handle commands that exit the shell
def precmd(self, line):
# remove leading/trailing whitespace
line = re.sub('^\s+|\s+$', '', line)
# don't do anything on empty lines
if line == '':
return ''
# terminate the shell
if re.match('quit|exit|eof', line, re.I):
print
sys.exit(0)
# don't attempt to login for some commands
if re.match('help|login|logout|whoami|history|clear', line, re.I):
return line
# login before attempting to run a command
#if not self.session:
#pdb.set_trace()
#self.do_login('')
#if self.session == '': return ''
parts = line.split()
if len(parts):
command = parts[0]
else:
return ''
if len(parts[1:]):
args = ' '.join(parts[1:])
else:
args = ''
# print the help message if the user passes '--help'
if re.search('--help', line):
return 'help %s' % command
# should we look for an item in the history?
if command[0] != '!' or len(command) < 2:
return line
# remove the '!*' line from the history
self.remove_last_history_item()
history_match = False
if command[1] == '!':
# repeat the last command
line = readline.get_history_item(
readline.get_current_history_length())
if line:
history_match = True
else:
logging.warning('%s: event not found' % command)
return ''
# attempt to find a numbered history item
if not history_match:
try:
number = int(command[1:])
line = readline.get_history_item(number)
if line:
history_match = True
else:
raise Exception
except IndexError:
pass
except ValueError:
pass
# attempt to match the beginning of the string with a history item
if not history_match:
history_range = range(1, readline.get_current_history_length())
history_range.reverse()
for i in history_range:
item = readline.get_history_item(i)
if re.match(command[1:], item):
line = item
history_match = True
break
# append the arguments to the substituted command
if history_match:
line += ' %s' % args
readline.add_history(line)
print line
return line
else:
logging.warning('%s: event not found' % command)
return ''
# update the prompt with the SSM size
def postcmd(self, stop, line):
self.prompt = re.sub('##', str(len(self.ssm)), self.prompt_template)
# vim:ts=4:expandtab: