From e9df73f6dc341567262c91dff144a4f9d453317e Mon Sep 17 00:00:00 2001 From: Frans de Jonge Date: Tue, 4 Apr 2017 09:57:14 +0200 Subject: [PATCH] Developer documentation improvements * Fixed up all of util and added when absent * Updated widget examples to new coding style --- frontend/ui/widget/infomessage.lua | 43 +++++------ frontend/ui/widget/inputdialog.lua | 2 +- frontend/ui/widget/textboxwidget.lua | 10 +-- frontend/util.lua | 106 +++++++++++++++++++-------- spec/unit/util_spec.lua | 8 +- 5 files changed, 108 insertions(+), 61 deletions(-) diff --git a/frontend/ui/widget/infomessage.lua b/frontend/ui/widget/infomessage.lua index e5601f889..f0ad3346d 100644 --- a/frontend/ui/widget/infomessage.lua +++ b/frontend/ui/widget/infomessage.lua @@ -1,30 +1,11 @@ -local Blitbuffer = require("ffi/blitbuffer") -local CenterContainer = require("ui/widget/container/centercontainer") -local Device = require("device") -local Font = require("ui/font") -local FrameContainer = require("ui/widget/container/framecontainer") -local Geom = require("ui/geometry") -local GestureRange = require("ui/gesturerange") -local HorizontalGroup = require("ui/widget/horizontalgroup") -local HorizontalSpan = require("ui/widget/horizontalspan") -local ImageWidget = require("ui/widget/imagewidget") -local InputContainer = require("ui/widget/container/inputcontainer") -local ScrollTextWidget = require("ui/widget/scrolltextwidget") -local TextBoxWidget = require("ui/widget/textboxwidget") -local UIManager = require("ui/uimanager") -local WidgetContainer = require("ui/widget/container/widgetcontainer") -local _ = require("gettext") -local Input = require("device").input -local Screen = require("device").screen - ---[[ +--[[-- Widget that displays an informational message it vanishes on key press or after a given timeout Example: - local _ = require("gettext") local UIManager = require("ui/uimanager") + local _ = require("gettext") local sample sample = InfoMessage:new{ text = _("Some message"), @@ -39,6 +20,26 @@ Example: sample_input:onShowKeyboard() UIManager:show(sample_input) ]] + +local Blitbuffer = require("ffi/blitbuffer") +local CenterContainer = require("ui/widget/container/centercontainer") +local Device = require("device") +local Font = require("ui/font") +local FrameContainer = require("ui/widget/container/framecontainer") +local Geom = require("ui/geometry") +local GestureRange = require("ui/gesturerange") +local HorizontalGroup = require("ui/widget/horizontalgroup") +local HorizontalSpan = require("ui/widget/horizontalspan") +local ImageWidget = require("ui/widget/imagewidget") +local InputContainer = require("ui/widget/container/inputcontainer") +local ScrollTextWidget = require("ui/widget/scrolltextwidget") +local TextBoxWidget = require("ui/widget/textboxwidget") +local UIManager = require("ui/uimanager") +local WidgetContainer = require("ui/widget/container/widgetcontainer") +local _ = require("gettext") +local Input = Device.input +local Screen = Device.screen + local InfoMessage = InputContainer:new{ modal = true, face = Font:getFace("infofont", 25), diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index 38d141a98..042b00e9d 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -3,8 +3,8 @@ Widget for taking user input. Example: - local _ = require("gettext") local UIManager = require("ui/uimanager") + local _ = require("gettext") local sample_input sample_input = InputDialog:new{ title = _("Dialog title"), diff --git a/frontend/ui/widget/textboxwidget.lua b/frontend/ui/widget/textboxwidget.lua index c559dc29b..f91e4d1c8 100644 --- a/frontend/ui/widget/textboxwidget.lua +++ b/frontend/ui/widget/textboxwidget.lua @@ -121,13 +121,13 @@ function TextBoxWidget:_splitCharWidthList() cur_line_text = table.concat(self.charlist, "", offset, idx - 1) else -- Backtrack the string until the length fit into one line. - -- We'll give next and prev chars to isSplitable() for a wiser decision + -- We'll give next and prev chars to isSplittable() for a wiser decision local c = self.char_width_list[idx].char local next_c = idx+1 <= size and self.char_width_list[idx+1].char or false local prev_c = idx-1 >= 1 and self.char_width_list[idx-1].char or false local adjusted_idx = idx local adjusted_width = cur_line_width - while adjusted_idx > offset and not util.isSplitable(c, next_c, prev_c) do + while adjusted_idx > offset and not util.isSplittable(c, next_c, prev_c) do adjusted_width = adjusted_width - self.char_width_list[adjusted_idx].width adjusted_idx = adjusted_idx - 1 next_c = c @@ -136,7 +136,7 @@ function TextBoxWidget:_splitCharWidthList() end if adjusted_idx == offset or adjusted_idx == idx then -- either a very long english word ocuppying more than one line, - -- or the excessive char is itself splitable: + -- or the excessive char is itself splittable: -- we let that excessive char for next line cur_line_text = table.concat(self.charlist, "", offset, idx - 1) cur_line_width = cur_line_width - self.char_width_list[idx].width @@ -147,8 +147,8 @@ function TextBoxWidget:_splitCharWidthList() cur_line_width = adjusted_width - self.char_width_list[adjusted_idx].width idx = adjusted_idx + 1 else - -- we backtracked and we're below max width, we can let the - -- splitable char on this line + -- we backtracked and we're below max width, we can leave the + -- splittable char on this line cur_line_text = table.concat(self.charlist, "", offset, adjusted_idx) cur_line_width = adjusted_width idx = adjusted_idx + 1 diff --git a/frontend/util.lua b/frontend/util.lua index 871c44032..851ae1c89 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -15,8 +15,9 @@ function util.stripePunctuations(text) return text:gsub("\226[\128-\131][\128-\191]", ''):gsub("^%p+", ''):gsub("%p+$", '') end ---- Splits a string by a pattern --[[-- +Splits a string by a pattern + Lua doesn't have a string.split() function and most of the time you don't really need it because string.gmatch() is enough. However string.gmatch() has one significant disadvantage for me: @@ -24,9 +25,12 @@ You can't split a string while matching both the delimited strings and the delimiters themselves without tracking positions and substrings. The gsplit function below takes care of this problem. + Author: Peter Odding + License: MIT/X11 -Source: http://snippets.luacode.org/snippets/String_splitting_130 + +Source: http://snippets.luacode.org/snippets/String_splitting_130 ]] ----@string str string to split ----@param pattern the pattern to split against @@ -58,8 +62,11 @@ function util.gsplit(str, pattern, capture) end) end ---- Converts seconds to a clock string. --- Source: https://gist.github.com/jesseadams/791673 +--[[-- +Converts seconds to a clock string. + +Source: https://gist.github.com/jesseadams/791673 +]] ---- @int seconds number of seconds ---- @bool withoutSeconds if true 00:00, if false 00:00:00 ---- @treturn string clock string in the form of 00:00 or 00:00:00 @@ -91,16 +98,26 @@ function util.tableSize(T) return count end --- append all elements from t2 into t1 +--- Append all elements from t2 into t1. +---- @param t1 Lua table +---- @param t2 Lua table function util.arrayAppend(t1, t2) for _, v in ipairs(t2) do table.insert(t1, v) end end --- Returns the index within this string of the last occurrence of the specified character --- or -1 if the character does not occur. --- To find . you need to escape it. +--[[-- +Gets last index of string in character + +Returns the index within this string of the last occurrence of the specified character +or -1 if the character does not occur. + +To find . you need to escape it. +]] +---- @string string +---- @string ch +---- @treturn int last occurrence or -1 if not found function util.lastIndexOf(string, ch) local i = string:match(".*" .. ch .. "()") if i == nil then return -1 else return i - 1 end @@ -125,12 +142,16 @@ function util.splitToChars(text) return tab end --- Tests whether c is a CJK character +--- Tests whether c is a CJK character +---- @string c +---- @treturn boolean true if CJK function util.isCJKChar(c) return string.match(c, "[\228-\234][\128-\191].") == c end --- Test whether str contains CJK characters +--- Tests whether str contains CJK characters +---- @string str +---- @treturn boolean true if CJK function util.hasCJKChar(str) return string.match(str, "[\228-\234][\128-\191].") ~= nil end @@ -158,15 +179,15 @@ end -- specific punctuation : e.g. "word :" or "word )" -- (In french, there is a space before a colon, and it better -- not be wrapped there.) -local non_splitable_space_tailers = ":;,.!?)]}$%=-+*/|<>»”" +local non_splittable_space_tailers = ":;,.!?)]}$%=-+*/|<>»”" -- Same if a space has some specific other punctuation before it -local non_splitable_space_leaders = "([{$=-+*/|<>«“" +local non_splittable_space_leaders = "([{$=-+*/|<>«“" -- Similar rules exist for CJK text. Taken from : -- https://en.wikipedia.org/wiki/Line_breaking_rules_in_East_Asian_languages -local cjk_non_splitable_tailers = table.concat( { +local cjk_non_splittable_tailers = table.concat( { -- Simplified Chinese "!%),.:;?]}¢°·’\"†‡›℃∶、。〃〆〕〗〞﹚﹜!"%'),.:;?!]}~", -- Traditional Chinese @@ -177,7 +198,7 @@ local cjk_non_splitable_tailers = table.concat( { "!%),.:;?]}¢°’\"†‡℃〆〈《「『〕!%),.:;?]}", }) -local cjk_non_splitable_leaders = table.concat( { +local cjk_non_splittable_leaders = table.concat( { -- Simplified Chinese "$(£¥·‘\"〈《「『【〔〖〝﹙﹛$(.[{£¥", -- Traditional Chinese @@ -188,23 +209,27 @@ local cjk_non_splitable_leaders = table.concat( { "$([{£¥‘\"々〇〉》」〔$([{⦆¥₩#", }) -local cjk_non_splitable = table.concat( { +local cjk_non_splittable = table.concat( { -- Japanese "—…‥〳〴〵", }) --- Test whether a string could be separated by this char for multi-line rendering +--- Test whether a string can be separated by this char for multi-line rendering. -- Optional next or prev chars may be provided to help make the decision -function util.isSplitable(c, next_c, prev_c) +---- @string c +---- @string next_c +---- @string prev_c +---- @treturn boolean true if splittable, false if not +function util.isSplittable(c, next_c, prev_c) if util.isCJKChar(c) then - -- a CJKChar is a word in itself, and so is splitable - if cjk_non_splitable:find(c, 1, true) then + -- a CJKChar is a word in itself, and so is splittable + if cjk_non_splittable:find(c, 1, true) then -- except a few of them return false - elseif next_c and cjk_non_splitable_tailers:find(next_c, 1, true) then + elseif next_c and cjk_non_splittable_tailers:find(next_c, 1, true) then -- but followed by a char that is not permitted at start of line return false - elseif prev_c and cjk_non_splitable_leaders:find(prev_c, 1, true) then + elseif prev_c and cjk_non_splittable_leaders:find(prev_c, 1, true) then -- but preceded by a char that is not permitted at end of line return false else @@ -214,10 +239,10 @@ function util.isSplitable(c, next_c, prev_c) elseif c == " " then -- we only split on a space (so punctuation sticks to prev word) -- if next_c or prev_c is provided, we can make a better decision - if next_c and non_splitable_space_tailers:find(next_c, 1, true) then + if next_c and non_splittable_space_tailers:find(next_c, 1, true) then -- this space is followed by some punctuation that is better kept with us return false - elseif prev_c and non_splitable_space_leaders:find(prev_c, 1, true) then + elseif prev_c and non_splittable_space_leaders:find(prev_c, 1, true) then -- this space is lead by some punctuation that is better kept with us return false else @@ -225,13 +250,15 @@ function util.isSplitable(c, next_c, prev_c) return true end end - -- otherwise, non splitable + -- otherwise, non splittable return false end ---- Gets filesystem type of a path --- Checks if the path occurs in /proc/mounts -----@string path an absolute path +--- Gets filesystem type of a path. +-- +-- Checks if the path occurs in /proc/mounts +---- @string path an absolute path +---- @treturn string filesystem type function util.getFilesystemType(path) local mounts = io.open("/proc/mounts", "r") if not mounts then return nil end @@ -255,37 +282,55 @@ function util.getFilesystemType(path) return type end +--- Replaces characters that are invalid filenames. +-- +-- Replaces the characters \/:*?"<>| with an _. +-- These characters are problematic on Windows filesystems. On Linux only +-- / poses a problem. +---- @string str filename +---- @treturn string sanitized filename function util.replaceInvalidChars(str) if str then return str:gsub('[\\,%/,:,%*,%?,%",%<,%>,%|]','_') end end +--- Replaces slash with an underscore. +---- @string str +---- @treturn string function util.replaceSlashChar(str) if str then return str:gsub('%/','_') end end --- Split a file into its path and name +--- Splits a file into its path and name +---- @string file +---- @treturn string path, filename function util.splitFilePathName(file) if file == nil or file == "" then return "", "" end if string.find(file, "/") == nil then return "", file end return string.gsub(file, "(.*/)(.*)", "%1"), string.gsub(file, ".*/", "") end --- Split a file name into its pure file name and suffix +--- Splits a file name into its pure file name and suffix +---- @string file +---- @treturn string path, extension function util.splitFileNameSuffix(file) if file == nil or file == "" then return "", "" end if string.find(file, "%.") == nil then return file, "" end return string.gsub(file, "(.*)%.(.*)", "%1"), string.gsub(file, ".*%.", "") end +--- Gets file extension +---- @string filename +---- @treturn string extension function util.getFileNameSuffix(file) local _, suffix = util.splitFileNameSuffix(file) return suffix end +--- Adds > to touch menu items with a submenu function util.getMenuText(item) local text if item.text_func then @@ -299,8 +344,9 @@ function util.getMenuText(item) return text end --- from http://notebook.kulchenko.com/programming/fixing-malformed-utf8-in-lua with modification --- Replaces invalid UTF-8 characters with a replacement string. +-- +-- Based on http://notebook.kulchenko.com/programming/fixing-malformed-utf8-in-lua ---- @string str the string to be checked for invalid characters ---- @string replacement the string to replace invalid characters with ---- @treturn string valid UTF-8 diff --git a/spec/unit/util_spec.lua b/spec/unit/util_spec.lua index 1edc85a53..eeb9eb6d6 100644 --- a/spec/unit/util_spec.lua +++ b/spec/unit/util_spec.lua @@ -86,7 +86,7 @@ describe("util module", function() for i = 1, #table_chars do c = table_chars[i] word = word .. c - if util.isSplitable(c) then + if util.isSplittable(c) then table.insert(table_of_words, word) word = "" end @@ -113,7 +113,7 @@ describe("util module", function() for i = 1, #table_chars do c = table_chars[i] word = word .. c - if util.isSplitable(c) then + if util.isSplittable(c) then table.insert(table_of_words, word) word = "" end @@ -134,7 +134,7 @@ describe("util module", function() c = table_chars[i] next_c = i < #table_chars and table_chars[i+1] or nil word = word .. c - if util.isSplitable(c, next_c) then + if util.isSplittable(c, next_c) then table.insert(table_of_words, word) word = "" end @@ -168,7 +168,7 @@ describe("util module", function() next_c = i < #table_chars and table_chars[i+1] or nil prev_c = i > 1 and table_chars[i-1] or nil word = word .. c - if util.isSplitable(c, next_c, prev_c) then + if util.isSplittable(c, next_c, prev_c) then table.insert(table_of_words, word) word = "" end