Re: command entry suggestion

From: Jay <robert.jay.go....at.gmail.com>
Date: Sun, 6 Jun 2010 05:17:01 -0700 (PDT)

Done, got all the features ready now. Only haven't properly
modularized it yet. Right now I placed this into my ~/.textadept
folder so it overrides the original file due to USERHOME coming before
HOME in lua's path.

Anyways it's usable now so here it is:
----command_entry.lua
-- Copyright 2007-2009 Mitchell Foral mitchell<att>caladbolg.net. See
LICENSE.

local util = {}

local textadept = _G.textadept
local locale = _G.locale
local type = _G.type
local rawget = _G.rawget
local rawset = _G.rawset
local select = _G.select
local ipairs = _G.ipairs
local tostring = _G.tostring
local unpack = _G.unpack

util.print = function(...)
        if select("#",...) > 1 then
                local t = {}
                for i,v in ipairs({...}) do
                        t[i]=tostring(v)
                end
                textadept.print(unpack(t))
        else
                textadept.print(tostring(...))
        end
end

util.printf = function(text,...)
        textadept.print(tostring(text):format(...))
end

util.append = function (text,...)
        buffer:append_text(tostring(text):format(...))
end

util.insertf = function (text,...)
        buffer:insert_text(buffer.current_pos, tostring(text):format(...))
end

util.insert = function (...)
        if select("#",...) > 1 then
                local t = {}
                for i,v in ipairs({...}) do
                        t[i]=tostring(v)
                end
                buffer:insert_text(buffer.current_pos,table.concat(t," "))
        else
                buffer:insert_text(buffer.current_pos, tostring(...))
        end
end

util.shell = function(text,...)
        return
textadept.iconv(_G.io.popen(text:format(...)):read("*all"),"UTF-8",_CHARSET)
end

util = setmetatable(util,{
__index = function(e,k)
        -- most operations are buffer shortcut
        local v = buffer[k]
        if type(v) ~= "nil" then
                if type(v)=="function" then
                        v = function(...)
                                buffer[k](buffer,...)
                        end
                end
        else -- or bindings to textadept
                v = textadept[k] or rawget(_G,k) -- if nothing was found default to
global
                if type(textadept[k])=="table" and type(rawget(_G,k))=="table" then--
then merge tables
                        v = {} --temprary merge table
                        for _1,_2 in pairs(textadept[k]) do
                                v[_1]=_2
                        end
                        for _1,_2 in pairs(rawget(_G,k)) do
                                v[_1]=_2
                        end
                end
        end
        --e[k] = v --memoize the key (don't memoize the key so newindex will
work correctly)
        return v
end,
__newindex = function(e,k,v)
        -- most operations are buffer shortcut
        local old = buffer[k]
        if type(old) ~= "nil" then
                buffer[k] = v --replace current
                return
        end
        old = textadept[k]
        if type(old) ~= "nil" then
                textadept[k] = v --replace current
                return
        end
        rawset(e,k,v)
end,
})

textadept.events.add_handler('command_entry_command',
  function(command) -- execute a Lua command
    local f, err = loadstring(command)
    if err then error(err) end
    textadept.command_entry.focus() -- toggle focus to hide
    setfenv(f,util)
        f()
  end)

textadept.events.add_handler('command_entry_keypress',
  function(code)
    local ce = textadept.command_entry
    if code == 0xff1b then -- escape
      ce.focus() -- toggle focus to hide
      return true
    elseif code == 0xff09 then -- tab
      local substring = ce.entry_text:match('[%w_.:]+$') or ''
      local path, o, prefix = substring:match('^([%w_.:]-)([.:]?)
([%w_]*)$')
          local f,err = loadstring('return ('..path..')')
          if type(f) == "function" then
                setfenv(f,util)
          end
      local ret, tbl = pcall(f)
          local cmpls = {}
      if not ret then
            --tbl = getfenv(0)
        for k in pairs(buffer) do
                  if type(k) == 'string' and k:find('^'..prefix) then
                        cmpls[#cmpls + 1] = k
                  end
                end
                for f in pairs(textadept.buffer_functions) do
                  if f:find('^'..prefix) then cmpls[#cmpls + 1] = f end
                end
                for p in pairs(textadept.buffer_properties) do
                  if p:find('^'..prefix) then cmpls[#cmpls + 1] = p end
                end
                for k in pairs(textadept) do
                  if type(k) == 'string' and k:find('^'..prefix) then
                        cmpls[#cmpls + 1] = k
                  end
                end
                for k in pairs(_G) do
                  if type(k) == 'string' and k:find('^'..prefix) then
                        cmpls[#cmpls + 1] = k
                  end
            end
          else
        if type(tbl) ~= 'table' then return end
        for k in pairs(tbl) do
          if type(k) == 'string' and k:find('^'..prefix) then
            cmpls[#cmpls + 1] = k
          end
        end
        if path == 'buffer' then
          if o == ':' then
            for f in pairs(textadept.buffer_functions) do
              if f:find('^'..prefix) then cmpls[#cmpls + 1] = f end
            end
          else
            for p in pairs(textadept.buffer_properties) do
              if p:find('^'..prefix) then cmpls[#cmpls + 1] = p end
            end
          end
        end
          end
      table.sort(cmpls)
      ce.show_completions(cmpls)
      return true
    end
  end)

On Jun 5, 12:20 am, Jay <robert.jay.go....at.gmail.com> wrote:
> just had some time now to get back to this, fixed the namespace
> clashing for io and keys and suggested, next is to get tab completion
> ready and modularize it. Hope to have it ready for testing this
> weekend.
>
> On May 17, 10:23 pm, mitchell <mforal.n....at.gmail.com> wrote:
>
>
>
> > Jay,
>
> > On May 17, 6:13 am, Jay <robert.jay.go....at.gmail.com> wrote:
>
> > > Unfortunately tab-completion doesn't work yet with the new system.
> > > Will need to change it I guess. Where is the code for it?
>
> > It's in the keypress handler for the 'tab' key (it's commented). I
> > think you'd only have to grab the current word text and see if it
> > exists in each global table you have a shortcut for.
>
> > Mitchell
>
> > > -Jay
>
> > > On May 11, 1:42 am, mitchell <mforal.n....at.gmail.com> wrote:
>
> > > > Jay,
>
> > > > On May 8, 5:43 am, Jay <robert.jay.go....at.gmail.com> wrote:
>
> > > > > Mitchell,
>
> > > > > That is a great idea indeed! I'll add the to the environment's
> > > > > metatable for keys and io to get the values from the right tables. Ok
> > > > > now that the prototype is basically ready. what would be the right
> > > > > place to put it? Should I extend command_entry? Or add a module (if so
> > > > > any good names)? Also I'd like to make it easy for users to add their
> > > > > own functions to the environment table (my currently called "utils"
> > > > > table). What design you think would be the most "textadept"ish?
> > > > > Something like key_commands that looks for a user file after setting
> > > > > the base functions?
>
> > > > I recommend providing it as a separate module right now (that can be
> > > > "require"d from ~/.textadept/init.lua). After testing, it will likely
> > > > go into ext/command_entry.lua and check a user file for extra
> > > > extensions because I think it would be really useful as a core
> > > > extension.
>
> > > > Out of curiousity, does the existing tab-completion work for your
> > > > code?
>
> > > > Mitchell
>
> > > > > -Jay
>
> > > > > On May 8, 11:51 am, mitchell <mforal.n....at.gmail.com> wrote:
>
> > > > > > On May 7, 10:43 pm, mitchell <mforal.n....at.gmail.com> wrote:
>
> > > > > > > Jay,
>
> > > > > > > On May 6, 8:34 am, Jay <robert.jay.go....at.gmail.com> wrote:
>
> > > > > > > > Finished, sort of.
>
> > > > > > > > I got the 'use_tabs = 1'  feature working by adding a __newindex to
> > > > > > > > the environment's metatable.
> > > > > > > > And luckily there are no clashes between 'textadept' and 'buffer',
> > > > > > > > woot!
>
> > > > > > > > however there are two conflicts:
> > > > > > > >   _G.io         textadept.io
> > > > > > > >   _G.keys    textadept.keys
>
> > > > > > > > First keys, 'textadept.keys' corresponds to the 'core/keys.lua',
> > > > > > > > '_G.keys' is 'core/ext/key_commands.lua'
> > > > > > > > Second io, '_G.io' is lua's basic io functionality, 'textadept.io' is
> > > > > > > > for file management.
>
> > > > > > > This is pretty awesome. I wonder if you can add a metatable to _G.io
> > > > > > > and _G.keys with __index such that if the key doesn't exist, look in
> > > > > > > textadept.io or textadept.keys because I don't think there are any
> > > > > > > index conflicts. The mixture could potentially be confusing, but at
> > > > > > > least it doesn't require renaming anything.
>
> > > > > > By metatable I mean local metatable (doesn't modify _G.io itself) in
> > > > > > the command entry environment.
>
> > > > > > Mitchell
>
> > > > > > > Mitchell
>
> > > > > > > > One possible solution would be to rename 'textadept.io' to
> > > > > > > > 'textadept.file' as that name is also appropriate and has no
> > > > > > > > conflicts,
> > > > > > > > and perhaps '_G.keys' could be 'commands' or something like that. this
> > > > > > > > way there would be no conflicts (although new one may still appear in
> > > > > > > > the future)
>
> > > > > > > > The next step would be to polish up utils, maybe rename to something
> > > > > > > > else and have it be easily extensible by calling user scripts like
> > > > > > > > other modules do right now.
>
> > > > > > > > Opinions?
>
> > > > > > > > And here is the beta code:
>
> > > > > > > > ----------- command_entry.lua ---------------
> > > > > > > > -- Copyright 2007-2009 Mitchell Foral mitchell<att>caladbolg.net. See
> > > > > > > > LICENSE.
>
> > > > > > > > local util = {}
>
> > > > > > > > local textadept = _G.textadept
> > > > > > > > local locale = _G.locale
> > > > > > > > local type = _G.type
> > > > > > > > local rawget = _G.rawget
> > > > > > > > local rawset = _G.rawset
> > > > > > > > local select = _G.select
> > > > > > > > local ipairs = _G.ipairs
> > > > > > > > local tostring = _G.tostring
> > > > > > > > local unpack = _G.unpack
>
> > > > > > > > util.printf = function(text,...)
> > > > > > > >         textadept.print(tostring(text):format(...))
> > > > > > > > end
>
> > > > > > > > util.appendf = function (text,...)
> > > > > > > >         buffer:append_text(tostring(text):format(...))
> > > > > > > > end
>
> > > > > > > > util.insertf = function (text,...)
> > > > > > > >         buffer:insert_text(buffer.current_pos, tostring(text):format(...))
> > > > > > > > end
>
> > > > > > > > util.shell = function(text,...)
> > > > > > > >         return
> > > > > > > > textadept.iconv(_G.io.popen(text:format(...)):read("*all"),"UTF-8",_CHARSET )
> > > > > > > > end
>
> > > > > > > > util = setmetatable(util,{
> > > > > > > > __index = function(e,k)
> > > > > > > >         -- most operations are buffer shortcut
> > > > > > > >         local v = buffer[k]
> > > > > > > >         if type(v) ~= "nil" then
> > > > > > > >                 if type(v)=="function" then
> > > > > > > >                         v = function(...)
> > > > > > > >                                 buffer[k](buffer,...)
> > > > > > > >                         end
> > > > > > > >                 end
> > > > > > > >         else -- or bindings to textadept
> > > > > > > >                 v = textadept[k] or rawget(_G,k) -- if nothing was found default to
> > > > > > > > global
> > > > > > > >         end
> > > > > > > >         --e[k] = v --memoize the key (don't memoize the key so newindex will
> > > > > > > > work correctly)
> > > > > > > >         return v
> > > > > > > > end,
> > > > > > > > __newindex = function(e,k,v)
> > > > > > > >         -- most operations are buffer shortcut
> > > > > > > >         local old = buffer[k]
> > > > > > > >         if type(old) ~= "nil" then
> > > > > > > >                 buffer[k] = v --replace current
> > > > > > > >                 return
> > > > > > > >         end
> > > > > > > >         old = textadept[k]
> > > > > > > >         if type(old) ~= "nil" then
> > > > > > > >                 textadept[k] = v --replace current
> > > > > > > >                 return
> > > > > > > >         end
> > > > > > > >         rawset(e,k,v)
> > > > > > > > end,
>
> > > > > > > > })
>
> > > > > > > > textadept.events.add_handler('command_entry_command',
> > > > > > > >   function(command) -- execute a Lua command
> > > > > > > >     local f, err = loadstring(command)
> > > > > > > >     if err then error(err) end
> > > > > > > >     textadept.command_entry.focus() -- toggle focus to hide
> > > > > > > >     setfenv(f,util)
> > > > > > > >         f()
> > > > > > > >   end)
>
> > > > > > > > textadept.events.add_handler('command_entry_keypress',
> > > > > > > >   function(code)
> > > > > > > >     local ce = textadept.command_entry
> > > > > > > >     if code == 0xff1b then -- escape
> > > > > > > >       ce.focus() -- toggle focus to hide
> > > > > > > >       return true
> > > > > > > >     elseif code == 0xff09 then -- tab
> > > > > > > >       local substring = ce.entry_text:match('[%w_.:]+$') or ''
> > > > > > > >       local path, o, prefix = substring:match('^([%w_.:]-)([.:]?)
> > > > > > > > ([%w_]*)$')
> > > > > > > >       local ret, tbl = pcall(loadstring('return ('..path..')'))
> > > > > > > >       if not ret then tbl = getfenv(0) end
> > > > > > > >       if type(tbl) ~= 'table' then return end
> > > > > > > >       local cmpls = {}
> > > > > > > >       for k in pairs(tbl) do
> > > > > > > >         if type(k) == 'string' and k:find('^'..prefix) then
> > > > > > > >           cmpls[#cmpls + 1] = k
> > > > > > > >         end
> > > > > > > >       end
> > > > > > > >       if path == 'buffer' then
> > > > > > > >         if o == ':' then
> > > > > > > >           for f in pairs(textadept.buffer_functions) do
> > > > > > > >             if f:find('^'..prefix) then cmpls[#cmpls + 1] = f end
> > > > > > > >           end
> > > > > > > >         else
> > > > > > > >           for p in pairs(textadept.buffer_properties) do
> > > > > > > >             if p:find('^'..prefix) then cmpls[#cmpls + 1] = p end
> > > > > > > >           end
> > > > > > > >         end
> > > > > > > >       end
> > > > > > > >       table.sort(cmpls)
> > > > > > > >       ce.show_completions(cmpls)
> > > > > > > >       return true
> > > > > > > >     end
> > > > > > > >   end)
>
> > > > > > > > ----------------- END ---------------------
>
> > > > > > > > On Apr 30, 2:10 pm, Jay <robert.jay.go....at.gmail.com> wrote:
>
> > > > > > > > > Mitchell,
>
> > > > > > > > > Glad you like it :)
> > > > > > > > > Yeah the name clashes happen, just had one yesterday.
> > > > > > > > > It happened while writing this shortcut for an an easy shell command
> > > > > > > > > [ insert(shell"grep stuff log.log") ] .
>
> > > > > > > > > -----
> > > > > > > > > util.shell = function(text,...)
> > > > > > > > >         return
> > > > > > > > > textadept.iconv(_G.io.popen(text:format(...)):read("*all"),"UTF-8",_CHARSET )
> > > > > > > > > -- Here was my first name clash, between textadept.io and _G.io
> > > > > > > > > end
> > > > > > > > > ----
>
> ...
>
Received on Sun 06 Jun 2010 - 08:17:01 EDT

This archive was generated by hypermail 2.2.0 : Thu 08 Mar 2012 - 11:44:18 EST