menubar: quote special chars

- Simplified & renamed nocase function
 - Add pattern-quoting functions to awful.util:
   - awful.util.query_to_pattern
   - awful.util.quote_pattern
 - awful.util: Add basic unit tests for menubar query

Fixes https://github.com/awesomeWM/awesome/issues/84.
This commit is contained in:
Roy Crihfield 2015-01-21 19:30:13 -05:00 committed by Daniel Hahler
parent 704cf21b68
commit 02bfd06038
2 changed files with 40 additions and 17 deletions

View File

@ -478,6 +478,39 @@ function util.table.iterate(t, filter, start)
end end
end end
-- Escape all special pattern-matching characters so that lua interprets them
-- literally instead of as a character class.
-- Source: http://stackoverflow.com/a/20778724/15690
function util.quote_pattern(s)
-- All special characters escaped in a string: %%, %^, %$, ...
local patternchars = '['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..']'
return string.gsub(s, patternchars, "%%%1")
end
-- Generate a pattern matching expression that ignores case.
-- @param s Original pattern matching expression.
function util.query_to_pattern(q)
s = util.quote_pattern(q)
-- Poor man's case-insensitive character matching.
s = string.gsub(s, "%a",
function (c)
return string.format("[%s%s]", string.lower(c),
string.upper(c))
end)
return s
end
function util.unittest()
local function testquery(q, s)
print('testquery("'..q..'", "'..s..'")')
local p = util.query_to_pattern("downlow")
local s = "DownLow"
assert(s:match(p))
end
testquery("downlow", "DownLow")
testquery("%word", "%word")
end
return util return util
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -79,17 +79,6 @@ local function colortext(s, c)
return "<span color='" .. c .. "'>" .. s .. "</span>" return "<span color='" .. c .. "'>" .. s .. "</span>"
end end
-- Generate a pattern matching expression that ignores case.
-- @param s Original pattern matching expresion.
local function nocase (s)
s = string.gsub(s, "%a",
function (c)
return string.format("[%s%s]", string.lower(c),
string.upper(c))
end)
return s
end
-- Get how the menu item should be displayed. -- Get how the menu item should be displayed.
-- @param o The menu item. -- @param o The menu item.
-- @return item name, item background color, background image, item icon. -- @return item name, item background color, background image, item icon.
@ -125,6 +114,7 @@ end
-- @param query The text to filter entries by. -- @param query The text to filter entries by.
local function menulist_update(query) local function menulist_update(query)
local query = query or "" local query = query or ""
local pattern = awful.util.query_to_pattern(query)
shownitems = {} shownitems = {}
local match_inside = {} local match_inside = {}
@ -137,8 +127,8 @@ local function menulist_update(query)
for _, v in pairs(menubar.menu_gen.all_categories) do for _, v in pairs(menubar.menu_gen.all_categories) do
v.focused = false v.focused = false
if not current_category and v.use then if not current_category and v.use then
if string.match(v.name, nocase(query)) then if string.match(v.name, pattern) then
if string.match(v.name, "^" .. nocase(query)) then if string.match(v.name, "^" .. pattern) then
table.insert(shownitems, v) table.insert(shownitems, v)
else else
table.insert(match_inside, v) table.insert(match_inside, v)
@ -152,10 +142,10 @@ local function menulist_update(query)
for i, v in ipairs(menu_entries) do for i, v in ipairs(menu_entries) do
v.focused = false v.focused = false
if not current_category or v.category == current_category then if not current_category or v.category == current_category then
if string.match(v.name, nocase(query)) if string.match(v.name, pattern)
or string.match(v.cmdline, nocase(query)) then or string.match(v.cmdline, pattern) then
if string.match(v.name, "^" .. nocase(query)) if string.match(v.name, "^" .. pattern)
or string.match(v.cmdline, "^" .. nocase(query)) then or string.match(v.cmdline, "^" .. pattern) then
table.insert(shownitems, v) table.insert(shownitems, v)
else else
table.insert(match_inside, v) table.insert(match_inside, v)