Advertisement
osmarks

textutils.prompt

Jan 31st, 2019
1,901
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.19 KB | None | 0 0
  1. --[[
  2. Features:
  3.  
  4. - All arguments are put into a table, so that they don't have to be put in any particular order, like how it is in read().
  5. - Type error protection has been condensed into a more understandable form.
  6. - Adds a few arguments, including those from read(), and others that would never make it into read():
  7.   - replaceChar (_sReplaceChar)
  8.   - history (_tHistory)
  9.   - complete (_fnComplete)
  10.   - prefix (_sDefault)
  11.   - limit (number): Size of the input box, defaults to the end of the screen
  12.   - newline (boolean): If set to false will remove the newline read appends
  13.   - completeBGColor (number): Changes the Background color of the suggested completion values
  14.   - completeTextColor (number): Changes the Text color of the suggested completion values
  15.   - filter (function): takes the current input string and feeds it to a function. The function can then manipulate the string and return it.
  16.   - writer (function): changes the function that is used to write to the screen.
  17.   - customkeys (table): a table consisting of all the "special" keys, any and all of which can now be redirected to any other key. Keys that can be redirected (if not redirected, their default is just the key name, prefixed by "keys."):
  18.     - enter
  19.     - up
  20.     - down
  21.     - left
  22.     - right
  23.     - backspace
  24.     - home
  25.     - delete
  26.     - tab
  27.     - end (["end"])
  28. ]]
  29. return function( _tOptions )
  30.     local tVerify = {replaceChar = "string", history = "table", complete = "function", prefix = "string", limit = "number", newline = "boolean", completeBGColor = "number", completeTextColor = "number", filter = "function", customkeys = "table", writer = "function"}
  31.     if not _tOptions then
  32.         _tOptions = {}
  33.     end
  34.     for k, v in pairs(tVerify) do
  35.         if _tOptions[k] ~= nil and type( _tOptions[k] ) ~= v then
  36.             error( "bad argument " .. k .. " (expected " .. v .. " got ".. type( _tOptions[k] ) .. ")", 2)
  37.         end
  38.     end
  39.    
  40.     term.setCursorBlink( true )
  41.  
  42.     local sLine
  43.     if type( _tOptions.prefix ) == "string" then
  44.         sLine = _tOptions.prefix
  45.     else
  46.         sLine = ""
  47.     end
  48.     local nhistoryPos
  49.     local nPos = #sLine
  50.     if _tOptions.replaceChar then
  51.         _tOptions.replaceChar = string.sub( _tOptions.replaceChar, 1, 1 )
  52.     end
  53.     if not _tOptions.customkeys then
  54.         _tOptions.customkeys = {}
  55.     end
  56.     local tCustomKeyNames = {enter = keys.enter, up = keys.up, down = keys.down, left = keys.left, right = keys.right, backspace = keys.backspace, home = keys.home, delete = keys.delete, tab = keys.tab, ["end"] = keys["end"]}
  57.     for k, v in pairs(tCustomKeyNames) do
  58.         if not _tOptions.customkeys[k] then
  59.             _tOptions.customkeys[k] = v
  60.         end
  61.     end
  62.  
  63.     local tCompletions
  64.     local nCompletion
  65.     local function recomplete()
  66.         if _tOptions.complete and nPos == string.len(sLine) then
  67.             tCompletions = _tOptions.complete( sLine )
  68.             if tCompletions and #tCompletions > 0 then
  69.                 nCompletion = 1
  70.             else
  71.                 nCompletion = nil
  72.             end
  73.         else
  74.             tCompletions = nil
  75.             nCompletion = nil
  76.         end
  77.     end
  78.  
  79.     local function uncomplete()
  80.         tCompletions = nil
  81.         nCompletion = nil
  82.     end
  83.    
  84.     local sx = term.getCursorPos()
  85.    
  86.     local w
  87.     if not _tOptions.limit then
  88.         w = term.getSize()
  89.     else
  90.         w = _tOptions.limit+sx
  91.     end
  92.    
  93.     local writeFunc = term.write
  94.    
  95.     if _tOptions.writer then
  96.         writeFunc = _tOptions.writer
  97.     end
  98.  
  99.     local function redraw( _bClear )
  100.         local nScroll = 0
  101.         if sx + nPos >= w then
  102.             nScroll = (sx + nPos) - w
  103.         end
  104.  
  105.         local cx,cy = term.getCursorPos()
  106.         term.setCursorPos( sx, cy )
  107.         local sReplace = (_bClear and " ") or _tOptions.replaceChar
  108.         if sReplace then
  109.             writeFunc( string.sub( string.rep( sReplace, math.max( string.len(sLine) + 1, 0 ) ),  nScroll + 1, nScroll + w ) )
  110.         else
  111.             writeFunc( string.sub( sLine, nScroll + 1, nScroll + w ) )
  112.         end
  113.  
  114.         if nCompletion then
  115.             local sCompletion = tCompletions[ nCompletion ]
  116.             local oldText, oldBg
  117.             if not _bClear then
  118.                 oldText = term.getTextColor()
  119.                 oldBg = term.getBackgroundColor()
  120.                 if not _tOptions.completeTextColor then
  121.                     term.setTextColor( colors.white )
  122.                 else
  123.                     term.setTextColor( _tOptions.completeTextColor )
  124.                 end
  125.                 if not _tOptions.completeBGColor then
  126.                     term.setBackgroundColor( colors.gray )
  127.                 else
  128.                     term.setBackgroundColor( _tOptions.completeBGColor )
  129.                 end
  130.             end
  131.             if sReplace then
  132.                 writeFunc( string.rep( sReplace, string.len( sCompletion ) ) )
  133.             else
  134.                 writeFunc( sCompletion )
  135.             end
  136.             if not _bClear then
  137.                 term.setTextColor( oldText )
  138.                 term.setBackgroundColor( oldBg )
  139.             end
  140.         end
  141.  
  142.         term.setCursorPos( sx + nPos - nScroll, cy )
  143.     end
  144.    
  145.     local function clear()
  146.         redraw( true )
  147.     end
  148.    
  149.     recomplete()
  150.     redraw()
  151.  
  152.     local function acceptCompletion()
  153.         if nCompletion then
  154.             -- Clear
  155.             clear()
  156.  
  157.             -- Find the common prefix of all the other suggestions which start with the same letter as the current one
  158.             local sCompletion = tCompletions[ nCompletion ]
  159.             sLine = sLine .. sCompletion
  160.             nPos = string.len( sLine )
  161.  
  162.             -- Redraw
  163.             recomplete()
  164.             redraw()
  165.         end
  166.     end
  167.     while true do
  168.         local sEvent, param = os.pullEvent()
  169.  
  170.         if sEvent == "char" then
  171.             -- Typed key
  172.             clear()
  173.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  174.             nPos = nPos + 1
  175.             recomplete()
  176.             redraw()
  177.  
  178.         elseif sEvent == "paste" then
  179.             -- Pasted text
  180.             clear()
  181.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  182.             nPos = nPos + string.len( param )
  183.             recomplete()
  184.             redraw()
  185.  
  186.         elseif sEvent == "key" then
  187.             if _tOptions.customkeys.enter == param then
  188.                 -- Enter
  189.                 if nCompletion then
  190.                     clear()
  191.                     uncomplete()
  192.                     redraw()
  193.                 end
  194.                 break
  195.                
  196.             elseif _tOptions.customkeys.left == param then
  197.                 -- Left
  198.                 if nPos > 0 then
  199.                     clear()
  200.                     nPos = nPos - 1
  201.                     recomplete()
  202.                     redraw()
  203.                 end
  204.                
  205.             elseif _tOptions.customkeys.right == param then
  206.                 -- Right                
  207.                 if nPos < string.len(sLine) then
  208.                     -- Move right
  209.                     clear()
  210.                     nPos = nPos + 1
  211.                     recomplete()
  212.                     redraw()
  213.                 else
  214.                     -- Accept autocomplete
  215.                     acceptCompletion()
  216.                 end
  217.  
  218.             elseif  _tOptions.customkeys.up == param or _tOptions.customkeys.down == param then
  219.                 -- Up or down
  220.                 if nCompletion then
  221.                     -- Cycle completions
  222.                     clear()
  223.                     if _tOptions.customkeys.up == param then
  224.                         nCompletion = nCompletion - 1
  225.                         if nCompletion < 1 then
  226.                             nCompletion = #tCompletions
  227.                         end
  228.                     elseif _tOptions.customkeys.down == param then
  229.                         nCompletion = nCompletion + 1
  230.                         if nCompletion > #tCompletions then
  231.                             nCompletion = 1
  232.                         end
  233.                     end
  234.                     redraw()
  235.  
  236.                 elseif _tOptions.history then
  237.                     -- Cycle history
  238.                     clear()
  239.                     if _tOptions.customkeys.up == param then
  240.                         -- Up
  241.                         if nhistoryPos == nil then
  242.                             if #_tOptions.history > 0 then
  243.                                 nhistoryPos = #_tOptions.history
  244.                             end
  245.                         elseif nhistoryPos > 1 then
  246.                             nhistoryPos = nhistoryPos - 1
  247.                         end
  248.                     elseif _tOptions.customkeys.down == param then
  249.                         -- Down
  250.                         if nhistoryPos == #_tOptions.history then
  251.                             nhistoryPos = nil
  252.                         elseif nhistoryPos ~= nil then
  253.                             nhistoryPos = nhistoryPos + 1
  254.                         end                        
  255.                     end
  256.                     if nhistoryPos then
  257.                         sLine = _tOptions.history[nhistoryPos]
  258.                         nPos = string.len( sLine )
  259.                     else
  260.                         sLine = ""
  261.                         nPos = 0
  262.                     end
  263.                     uncomplete()
  264.                     redraw()
  265.  
  266.                 end
  267.  
  268.             elseif _tOptions.customkeys.backspace == param then
  269.                 -- Backspace
  270.                 if nPos > 0 then
  271.                     clear()
  272.                     sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
  273.                     nPos = nPos - 1
  274.                     recomplete()
  275.                     redraw()
  276.                 end
  277.  
  278.             elseif _tOptions.customkeys.home == param then
  279.                 -- Home
  280.                 if nPos > 0 then
  281.                     clear()
  282.                     nPos = 0
  283.                     recomplete()
  284.                     redraw()
  285.                 end
  286.  
  287.             elseif _tOptions.customkeys.delete == param then
  288.                 -- Delete
  289.                 if nPos < string.len(sLine) then
  290.                     clear()
  291.                     sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
  292.                     recomplete()
  293.                     redraw()
  294.                 end
  295.  
  296.             elseif _tOptions.customkeys["end"] == param then
  297.                 -- End
  298.                 if nPos < string.len(sLine ) then
  299.                     clear()
  300.                     nPos = string.len(sLine)
  301.                     recomplete()
  302.                     redraw()
  303.                 end
  304.  
  305.             elseif _tOptions.customkeys.tab == param then
  306.                 -- Tab (accept autocomplete)
  307.                 acceptCompletion()
  308.  
  309.             end
  310.        
  311.         elseif sEvent == "term_resize" then
  312.             -- Terminal resized
  313.             if not _tOptions.limit then
  314.                 w = term.getSize()
  315.             else
  316.                 w = _tOptions.limit
  317.             end
  318.             redraw()
  319.  
  320.         end
  321.  
  322.         if _tOptions.filter then
  323.             -- Filter out all unwanted characters/strings using a function defined by the user
  324.             local sPreFilterLine = sLine
  325.             sLine = _tOptions.filter( sLine )
  326.             if string.len( sPreFilterLine ) ~= string.len( sLine ) then
  327.                 local sPreClearLine = sLine
  328.                 sLine = sPreFilterLine
  329.                 clear()
  330.                 sLine = sPreClearLine
  331.             end
  332.             if not sLine then
  333.                 sLine = sPreFilterLine
  334.             else
  335.                 if nPos >= ( string.len( sPreFilterLine ) - string.len( sLine ) ) then
  336.                     nPos = nPos - ( string.len( sPreFilterLine ) - string.len( sLine ) )
  337.                 else
  338.                     nPos = 0
  339.                 end
  340.             end
  341.             redraw()
  342.         end
  343.     end
  344.  
  345.     local cx, cy = term.getCursorPos()
  346.     term.setCursorBlink( false )
  347.     if _tOptions.newline == nil or _tOptions.newline == true then
  348.         term.setCursorPos( 1, cy + 1)
  349.     end
  350.    
  351.     return sLine
  352. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement