Sirshark10

test

Mar 25th, 2017
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.16 KB | None | 0 0
  1.  
  2. local multishell = multishell
  3. local parentShell = shell
  4. local parentTerm = term.current()
  5.  
  6. local bExit = false
  7. local sDir = (parentShell and parentShell.dir()) or ""
  8. local sPath = (parentShell and parentShell.path()) or ".:/rom/programs"
  9. local tAliases = (parentShell and parentShell.aliases()) or {}
  10. local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}
  11. local tProgramStack = {}
  12.  
  13. local shell = {}
  14. local tEnv = {
  15. [ "shell" ] = shell,
  16. [ "multishell" ] = multishell,
  17. }
  18.  
  19. -- Colours
  20. local promptColour, textColour, bgColour
  21. if term.isColour() then
  22. promptColour = colours.yellow
  23. textColour = colours.white
  24. bgColour = colours.black
  25. else
  26. promptColour = colours.white
  27. textColour = colours.white
  28. bgColour = colours.black
  29. end
  30.  
  31. local function run( _sCommand, ... )
  32. local sPath = shell.resolveProgram( _sCommand )
  33. if sPath ~= nil then
  34. tProgramStack[#tProgramStack + 1] = sPath
  35. if multishell then
  36. multishell.setTitle( multishell.getCurrent(), fs.getName( sPath ) )
  37. end
  38. local result = os.run( tEnv, sPath, ... )
  39. tProgramStack[#tProgramStack] = nil
  40. if multishell then
  41. if #tProgramStack > 0 then
  42. multishell.setTitle( multishell.getCurrent(), fs.getName( tProgramStack[#tProgramStack] ) )
  43. else
  44. multishell.setTitle( multishell.getCurrent(), "shell" )
  45. end
  46. end
  47. return result
  48. else
  49. printError( "No such program" )
  50. return false
  51. end
  52. end
  53.  
  54. local function tokenise( ... )
  55. local sLine = table.concat( { ... }, " " )
  56. local tWords = {}
  57. local bQuoted = false
  58. for match in string.gmatch( sLine .. "\"", "(.-)\"" ) do
  59. if bQuoted then
  60. table.insert( tWords, match )
  61. else
  62. for m in string.gmatch( match, "[^ \t]+" ) do
  63. table.insert( tWords, m )
  64. end
  65. end
  66. bQuoted = not bQuoted
  67. end
  68. return tWords
  69. end
  70.  
  71. -- Install shell API
  72. function shell.run( ... )
  73. local tWords = tokenise( ... )
  74. local sCommand = tWords[1]
  75. if sCommand then
  76. return run( sCommand, table.unpack( tWords, 2 ) )
  77. end
  78. return false
  79. end
  80.  
  81. function shell.exit()
  82. bExit = true
  83. end
  84.  
  85. function shell.dir()
  86. return sDir
  87. end
  88.  
  89. function shell.setDir( _sDir )
  90. sDir = _sDir
  91. end
  92.  
  93. function shell.path()
  94. return sPath
  95. end
  96.  
  97. function shell.setPath( _sPath )
  98. sPath = _sPath
  99. end
  100.  
  101. function shell.resolve( _sPath )
  102. local sStartChar = string.sub( _sPath, 1, 1 )
  103. if sStartChar == "/" or sStartChar == "\\" then
  104. return fs.combine( "", _sPath )
  105. else
  106. return fs.combine( sDir, _sPath )
  107. end
  108. end
  109.  
  110. function shell.resolveProgram( _sCommand )
  111. -- Substitute aliases firsts
  112. if tAliases[ _sCommand ] ~= nil then
  113. _sCommand = tAliases[ _sCommand ]
  114. end
  115.  
  116. -- If the path is a global path, use it directly
  117. local sStartChar = string.sub( _sCommand, 1, 1 )
  118. if sStartChar == "/" or sStartChar == "\\" then
  119. local sPath = fs.combine( "", _sCommand )
  120. if fs.exists( sPath ) and not fs.isDir( sPath ) then
  121. return sPath
  122. end
  123. return nil
  124. end
  125.  
  126. -- Otherwise, look on the path variable
  127. for sPath in string.gmatch(sPath, "[^:]+") do
  128. sPath = fs.combine( shell.resolve( sPath ), _sCommand )
  129. if fs.exists( sPath ) and not fs.isDir( sPath ) then
  130. return sPath
  131. end
  132. end
  133.  
  134. -- Not found
  135. return nil
  136. end
  137.  
  138. function shell.programs( _bIncludeHidden )
  139. local tItems = {}
  140.  
  141. -- Add programs from the path
  142. for sPath in string.gmatch(sPath, "[^:]+") do
  143. sPath = shell.resolve( sPath )
  144. if fs.isDir( sPath ) then
  145. local tList = fs.list( sPath )
  146. for n=1,#tList do
  147. local sFile = tList[n]
  148. if not fs.isDir( fs.combine( sPath, sFile ) ) and
  149. (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= ".") then
  150. tItems[ sFile ] = true
  151. end
  152. end
  153. end
  154. end
  155.  
  156. -- Sort and return
  157. local tItemList = {}
  158. for sItem, b in pairs( tItems ) do
  159. table.insert( tItemList, sItem )
  160. end
  161. table.sort( tItemList )
  162. return tItemList
  163. end
  164.  
  165. local function completeProgram( sLine )
  166. if #sLine > 0 and string.sub( sLine, 1, 1 ) == "/" then
  167. -- Add programs from the root
  168. return fs.complete( sLine, "", true, false )
  169.  
  170. else
  171. local tResults = {}
  172. local tSeen = {}
  173.  
  174. -- Add aliases
  175. for sAlias, sCommand in pairs( tAliases ) do
  176. if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then
  177. local sResult = string.sub( sAlias, #sLine + 1 )
  178. if not tSeen[ sResult ] then
  179. table.insert( tResults, sResult )
  180. tSeen[ sResult ] = true
  181. end
  182. end
  183. end
  184.  
  185. -- Add programs from the path
  186. local tPrograms = shell.programs()
  187. for n=1,#tPrograms do
  188. local sProgram = tPrograms[n]
  189. if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then
  190. local sResult = string.sub( sProgram, #sLine + 1 )
  191. if not tSeen[ sResult ] then
  192. table.insert( tResults, sResult )
  193. tSeen[ sResult ] = true
  194. end
  195. end
  196. end
  197.  
  198. -- Sort and return
  199. table.sort( tResults )
  200. return tResults
  201. end
  202. end
  203.  
  204. local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )
  205. local tInfo = tCompletionInfo[ sProgram ]
  206. if tInfo then
  207. return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )
  208. end
  209. return nil
  210. end
  211.  
  212. function shell.complete( sLine )
  213. if #sLine > 0 then
  214. local tWords = tokenise( sLine )
  215. local nIndex = #tWords
  216. if string.sub( sLine, #sLine, #sLine ) == " " then
  217. nIndex = nIndex + 1
  218. end
  219. if nIndex == 1 then
  220. local sBit = tWords[1] or ""
  221. local sPath = shell.resolveProgram( sBit )
  222. if tCompletionInfo[ sPath ] then
  223. return { " " }
  224. else
  225. local tResults = completeProgram( sBit )
  226. for n=1,#tResults do
  227. local sResult = tResults[n]
  228. local sPath = shell.resolveProgram( sBit .. sResult )
  229. if tCompletionInfo[ sPath ] then
  230. tResults[n] = sResult .. " "
  231. end
  232. end
  233. return tResults
  234. end
  235.  
  236. elseif nIndex > 1 then
  237. local sPath = shell.resolveProgram( tWords[1] )
  238. local sPart = tWords[nIndex] or ""
  239. local tPreviousParts = tWords
  240. tPreviousParts[nIndex] = nil
  241. return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )
  242.  
  243. end
  244. end
  245. return nil
  246. end
  247.  
  248. function shell.completeProgram( sProgram )
  249. return completeProgram( sProgram )
  250. end
  251.  
  252. function shell.setCompletionFunction( sProgram, fnComplete )
  253. tCompletionInfo[ sProgram ] = {
  254. fnComplete = fnComplete
  255. }
  256. end
  257.  
  258. function shell.getCompletionInfo()
  259. return tCompletionInfo
  260. end
  261.  
  262. function shell.getRunningProgram()
  263. if #tProgramStack > 0 then
  264. return tProgramStack[#tProgramStack]
  265. end
  266. return nil
  267. end
  268.  
  269. function shell.setAlias( _sCommand, _sProgram )
  270. tAliases[ _sCommand ] = _sProgram
  271. end
  272.  
  273. function shell.clearAlias( _sCommand )
  274. tAliases[ _sCommand ] = nil
  275. end
  276.  
  277. function shell.aliases()
  278. -- Copy aliases
  279. local tCopy = {}
  280. for sAlias, sCommand in pairs( tAliases ) do
  281. tCopy[sAlias] = sCommand
  282. end
  283. return tCopy
  284. end
  285.  
  286. if multishell then
  287. function shell.openTab( ... )
  288. local tWords = tokenise( ... )
  289. local sCommand = tWords[1]
  290. if sCommand then
  291. local sPath = shell.resolveProgram( sCommand )
  292. if sPath == "rom/programs/shell" then
  293. return multishell.launch( tEnv, sPath, table.unpack( tWords, 2 ) )
  294. elseif sPath ~= nil then
  295. return multishell.launch( tEnv, "rom/programs/shell", sCommand, table.unpack( tWords, 2 ) )
  296. else
  297. printError( "No such program" )
  298. end
  299. end
  300. end
  301.  
  302. function shell.switchTab( nID )
  303. multishell.setFocus( nID )
  304. end
  305. end
  306.  
  307. local tArgs = { ... }
  308. if #tArgs > 0 then
  309. -- "shell x y z"
  310. -- Run the program specified on the commandline
  311. shell.run( ... )
  312.  
  313. else
  314. -- "shell"
  315. -- Print the header
  316. term.setBackgroundColor( bgColour )
  317. term.setTextColour( promptColour )
  318. print( os.version() )
  319. term.setTextColour( textColour )
  320.  
  321. -- Run the startup program
  322. if parentShell == nil then
  323. shell.run( "/rom/startup" )
  324. end
  325.  
  326. -- Read commands and execute them
  327. local tCommandHistory = {}
  328. while not bExit do
  329. term.setBackgroundColor( bgColour )
  330. term.setTextColour( promptColour )
  331. write( shell.dir().."> " )
  332. term.setTextColour( textColour )
  333. local sLine
  334. if settings.get( "shell.autocomplete" ) then
  335. sLine = read( nil, tCommandHistory, shell.complete )
  336. else
  337. sLine = read( nil, tCommandHistory )
  338. end
  339. table.insert( tCommandHistory, sLine )
  340. shell.run( sLine )
  341. end
  342. end
Advertisement
Add Comment
Please, Sign In to add comment