From 02bfd06038a61d14a4c31576c62105aa174e2181 Mon Sep 17 00:00:00 2001 From: Roy Crihfield Date: Wed, 21 Jan 2015 19:30:13 -0500 Subject: [PATCH] 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. --- lib/awful/util.lua.in | 33 +++++++++++++++++++++++++++++++++ lib/menubar/init.lua.in | 24 +++++++----------------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/lib/awful/util.lua.in b/lib/awful/util.lua.in index 76c88e20..d9709b79 100644 --- a/lib/awful/util.lua.in +++ b/lib/awful/util.lua.in @@ -478,6 +478,39 @@ function util.table.iterate(t, filter, start) 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 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/menubar/init.lua.in b/lib/menubar/init.lua.in index 14606f0b..85d07bd5 100644 --- a/lib/menubar/init.lua.in +++ b/lib/menubar/init.lua.in @@ -79,17 +79,6 @@ local function colortext(s, c) return "" .. s .. "" 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. -- @param o The menu item. -- @return item name, item background color, background image, item icon. @@ -125,6 +114,7 @@ end -- @param query The text to filter entries by. local function menulist_update(query) local query = query or "" + local pattern = awful.util.query_to_pattern(query) shownitems = {} local match_inside = {} @@ -137,8 +127,8 @@ local function menulist_update(query) for _, v in pairs(menubar.menu_gen.all_categories) do v.focused = false if not current_category and v.use then - if string.match(v.name, nocase(query)) then - if string.match(v.name, "^" .. nocase(query)) then + if string.match(v.name, pattern) then + if string.match(v.name, "^" .. pattern) then table.insert(shownitems, v) else table.insert(match_inside, v) @@ -152,10 +142,10 @@ local function menulist_update(query) for i, v in ipairs(menu_entries) do v.focused = false if not current_category or v.category == current_category then - if string.match(v.name, nocase(query)) - or string.match(v.cmdline, nocase(query)) then - if string.match(v.name, "^" .. nocase(query)) - or string.match(v.cmdline, "^" .. nocase(query)) then + if string.match(v.name, pattern) + or string.match(v.cmdline, pattern) then + if string.match(v.name, "^" .. pattern) + or string.match(v.cmdline, "^" .. pattern) then table.insert(shownitems, v) else table.insert(match_inside, v)