Skip to content

Commit

Permalink
Add the ability to add new shortcuts to awful.prompt
Browse files Browse the repository at this point in the history
Example:

awful.prompt.run({ prompt = "Run: ", hooks = {
    {{         },"Return",function(command)
         local result = awful.util.spawn(command)
         mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
         return true
    end},
    {{"Mod1"   },"Return",function(command)
         local result = awful.util.spawn(command,{intrusive=true})
         mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
         return true
    end},
    {{"Shift"  },"Return",function(command)
         local result = awful.util.spawn(command,{intrusive=true,ontop=true,floating=true})
         mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
         return true
    end}
    }},...)
  • Loading branch information
Elv13 committed May 5, 2014
1 parent c694e25 commit 7e17801
Showing 1 changed file with 40 additions and 6 deletions.
46 changes: 40 additions & 6 deletions lib/awful/prompt.lua.in
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ local function prompt_text_with_cursor(args)
end

--- Run a prompt in a box.
-- @param args A table with optional arguments: fg_cursor, bg_cursor, ul_cursor, prompt, text, selectall, font, autoexec.
-- @param args A table with optional arguments: fg_cursor, bg_cursor, ul_cursor, prompt, text, selectall, font, autoexec, hooks.
-- @param textbox The textbox to use for the prompt.
-- @param exe_callback The callback function to call with command as argument when finished.
-- @param completion_callback The callback function to call to get completion.
Expand Down Expand Up @@ -195,6 +195,12 @@ end
-- <li><code>CTRL+DOWN</code>: ZSH down line or search, matches any history entry starting with search term</li>
-- <li><code>CTRL+DELETE</code>: delete the currently visible history entry from history file. <br/>Does not delete new commands or history entries under user editing</li>
-- </ul>
--
-- The "hooks" argument use a syntax similar awful.key:

This comment has been minimized.

Copy link
@psychon

psychon May 8, 2014

Collaborator

similar TO awful.key

-- <code> hooks = {
-- {{ "Control" }, "Return", function(text) end } ,
-- {{ }, "Tab", function(text) end }
-- } </code>
function prompt.run(args, textbox, exe_callback, completion_callback, history_path, history_max, done_callback, changed_callback, keypressed_callback)
local grabber
local theme = beautiful.get()
Expand All @@ -209,6 +215,7 @@ function prompt.run(args, textbox, exe_callback, completion_callback, history_pa
local text = args.text or ""
local font = args.font or theme.font
local selectall = args.selectall
local hooks = {}

search_term=nil

Expand All @@ -218,20 +225,30 @@ function prompt.run(args, textbox, exe_callback, completion_callback, history_pa
local cur_pos = (selectall and 1) or text:wlen() + 1
-- The completion element to use on completion request.
local ncomp = 1
if not textbox or not exe_callback then
if not textbox or not (exe_callback or args.hooks) then
return
end
-- Build the hook map
for k,v in ipairs(args.hooks or {}) do
if #v == 3 then
local mods,key,callback = unpack(v)
if type(callback) == "function" then

This comment has been minimized.

Copy link
@psychon

psychon May 8, 2014

Collaborator

Do we really want all these safety measures? If people pass in wrong arguments and they get silently dropped, they will debug this for a while. If people pass in wrong arguments and an error occurs, they will at least know that something is wrong (and they aren't seeing a ghost which drops hooks arguments).

hooks[key] = hooks[key] or {}
hooks[key][#hooks[key]+1] = v
end
end
end
textbox:set_font(font)
textbox:set_markup(prompt_text_with_cursor{
text = text, text_color = inv_col, cursor_color = cur_col,
cursor_pos = cur_pos, cursor_ul = cur_ul, selectall = selectall,
prompt = prettyprompt })

local exec = function()
local function exec(cb)
textbox:set_markup("")
history_add(history_path, command)
keygrabber.stop(grabber)
exe_callback(command)
cb(command)
if done_callback then done_callback() end
end

Expand Down Expand Up @@ -275,6 +292,23 @@ function prompt.run(args, textbox, exe_callback, completion_callback, history_pa
end
end

-- User defined cases
if hooks[key] then
for k,v in ipairs(hooks[key]) do
if #modifiers == #v[1] then
local match = true
for k2,v2 in ipairs(v[1]) do
match = match and mod[v2]

This comment has been minimized.

Copy link
@psychon

psychon May 8, 2014

Collaborator

This only allows checking if some modifier is pressed. It's not possible for some modifier to be released/disabled.

Since "false" and "nil" are different, could you do something like this (untested)?

for _, modifier in pairs(util.table.join(awful.util.keys(mod), v[1])) do
    match = match and (mod[modifier] == nil or mod[modifier] == v[1][modifier]
end

(I bet this code doesn't work, but you get the idea)

Oh and why is this "ipairs"? Doesn't this mean that this code doesn't work at all since modifiers are things like "Control" and not integers? (See my previous sentence saying that this likely doesn't work. That's because I apparently don't get it right now)

This comment has been minimized.

Copy link
@Elv13

Elv13 May 8, 2014

Author Owner

Control is the value, not the key, this patch is tested and work as advertised

This comment has been minimized.

Copy link
@psychon

psychon May 11, 2014

Collaborator

So... you are saying that if I have a keybinding for "ctrl+r" and press "shift+ctrl+r", it won't be triggered?

-- There is not enough modifiers to add a if then break end
end
if match or #modifiers == 0 then

This comment has been minimized.

Copy link
@psychon

psychon May 8, 2014

Collaborator

Why the #modifiers == 0 special case?

This comment has been minimized.

Copy link
@Elv13

Elv13 May 8, 2014

Author Owner

It is not a special case, the for loop wont find anything when there is no modifiers, it wont get into the loop. We already know that

  1. The key match
  2. The number of modifiers is the same

So if there is no modifiers, then it is a single key hook, then it is normal that the mods doesn't match as there is none.

This comment has been minimized.

Copy link
@psychon

psychon May 11, 2014

Collaborator

Ahhhhhh! I totally missed the "number of modifiers is the same" check before. That explains things for the previous comment.

But then.... "match" is initialized to true, the for loop never runs, so even if "#modifiers == 0", just the "match" check should be enough, shouldn't it?

exec(v[3])
return
end
end
end
end

-- Get out cases
if (mod.Control and (key == "c" or key == "g"))
or (not mod.Control and key == "Escape") then
Expand All @@ -286,7 +320,7 @@ function prompt.run(args, textbox, exe_callback, completion_callback, history_pa
elseif (mod.Control and (key == "j" or key == "m"))
or (not mod.Control and key == "Return")
or (not mod.Control and key == "KP_Enter") then
exec()
exec(exe_callback)
-- We already unregistered ourselves so we don't want to return
-- true, otherwise we may unregister someone else.
return
Expand Down Expand Up @@ -422,7 +456,7 @@ function prompt.run(args, textbox, exe_callback, completion_callback, history_pa
key = ""
-- execute if only one match found and autoexec flag set
if matches and #matches == 1 and args.autoexec then
exec()
exec(exe_callback)
return
end
else
Expand Down

1 comment on commit 7e17801

@psychon
Copy link
Collaborator

@psychon psychon commented on 7e17801 May 8, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the commit message: Could you use some non-tyrannical examples, please? Nothing with "intrusive" :P

Please sign in to comment.