From 98515a2210ba1de50dcb3e36c6335b2d71fb4079 Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 22 Apr 2015 14:15:04 +0800 Subject: [PATCH 1/3] Fix filemanager cp/mv/rm operations not work on Android --- base | 2 +- frontend/apps/filemanager/filemanager.lua | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/base b/base index ae6ea7e96..d2c53757a 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit ae6ea7e96c6695ed23aee84da1065b29e9fed0ea +Subproject commit d2c53757a098f3f17fec816bea638adc71e2976f diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 6ba1e128b..c943f0b00 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -26,6 +26,10 @@ local FileManager = InputContainer:extend{ -- our own size dimen = Geom:new{ w = 400, h = 600 }, onExit = function() end, + + mv_bin = Device:isAndroid() and "/system/bin/mv" or "/bin/mv", + cp_bin = Device:isAndroid() and "/system/bin/cp" or "/bin/cp", + rm_bin = Device:isAndroid() and "/system/bin/rm" or "/bin/rm", } function FileManager:init() @@ -265,9 +269,9 @@ function FileManager:pasteHere(file) local dest = lfs.attributes(file, "mode") == "directory" and file or file:match("(.*/)") if self.cutfile then - util.execute("/bin/mv", orig, dest) + util.execute(self.mv_bin, orig, dest) else - util.execute("/bin/cp", "-r", orig, dest) + util.execute(self.cp_bin, "-r", orig, dest) end end end @@ -275,7 +279,7 @@ end function FileManager:deleteFile(file) local InfoMessage = require("ui/widget/infomessage") DEBUG("File to remove", util.realpath(file)) - local rm = util.execute("/bin/rm", "-rf", util.realpath(file)) + local rm = util.execute(self.rm_bin, "-rf", util.realpath(file)) DEBUG("rm status", rm) if rm == 0 then UIManager:show(InfoMessage:new{ From 932df2a2f915ab08f1a9109072a87bc33201f71d Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 22 Apr 2015 14:17:06 +0800 Subject: [PATCH 2/3] Refactor out string.gsplit to util.gsplit --- frontend/ui/widget/textboxwidget.lua | 48 +++------------------------- frontend/util.lua | 39 ++++++++++++++++++++++ spec/unit/util_spec.lua | 36 +++++++++++++++++++++ 3 files changed, 79 insertions(+), 44 deletions(-) create mode 100644 spec/unit/util_spec.lua diff --git a/frontend/ui/widget/textboxwidget.lua b/frontend/ui/widget/textboxwidget.lua index b7bfd251d..8adcc40d3 100644 --- a/frontend/ui/widget/textboxwidget.lua +++ b/frontend/ui/widget/textboxwidget.lua @@ -3,8 +3,7 @@ local Widget = require("ui/widget/widget") local RenderText = require("ui/rendertext") local Screen = require("device").screen local Geom = require("ui/geometry") - --- TODO: rename string:gsplit definition +local util = require("util") --[[ A TextWidget that handles long text wrapping @@ -64,45 +63,6 @@ function TextBoxWidget:_wrapGreedyAlg(h_list) return v_list end ---[[ -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: -You can't split a string while matching both the delimited -strings and the delimiters themselves without tracking positions -and substrings. The string.gsplit() function below takes care of -this problem. -Author: Peter Odding -License: MIT/X11 -Source: http://snippets.luacode.org/snippets/String_splitting_130 ---]] -function string:gsplit(pattern, capture) - pattern = pattern and tostring(pattern) or '%s+' - if (''):find(pattern) then - error('pattern matches empty string!', 2) - end - return coroutine.wrap(function() - local index = 1 - repeat - local first, last = self:find(pattern, index) - if first and last then - if index < first then - coroutine.yield(self:sub(index, first - 1)) - end - if capture then - coroutine.yield(self:sub(first, last)) - end - index = last + 1 - else - if index <= #self then - coroutine.yield(self:sub(index)) - end - break - end - until index > #self - end) -end - function TextBoxWidget:_getVerticalList(alg) if self.vertical_list then return self.vertical_list @@ -110,10 +70,10 @@ function TextBoxWidget:_getVerticalList(alg) -- build horizontal list local h_list = {} local line_count = 0 - for line in self.text:gsplit("\n", true) do + for line in util.gsplit(self.text, "\n", true) do for words in line:gmatch("[\32-\127\192-\255]+[\128-\191]*") do - for word in words:gsplit("%s+", true) do - for w in word:gsplit("%p+", true) do + for word in util.gsplit(words, "%s+", true) do + for w in util.gsplit(word, "%p+", true) do local word_box = {} word_box.word = w word_box.width = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, w, true, self.bold).x diff --git a/frontend/util.lua b/frontend/util.lua index ff1fbe4e1..5eff42fef 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -8,4 +8,43 @@ function util.stripePunctuations(word) return word:gsub("\226[\128-\131][\128-\191]",''):gsub("^%p+",''):gsub("%p+$",'') end +--[[ +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: +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 +--]] +function util.gsplit(str, pattern, capture) + pattern = pattern and tostring(pattern) or '%s+' + if (''):find(pattern) then + error('pattern matches empty string!', 2) + end + return coroutine.wrap(function() + local index = 1 + repeat + local first, last = str:find(pattern, index) + if first and last then + if index < first then + coroutine.yield(str:sub(index, first - 1)) + end + if capture then + coroutine.yield(str:sub(first, last)) + end + index = last + 1 + else + if index <= #str then + coroutine.yield(str:sub(index)) + end + break + end + until index > #str + end) +end + return util diff --git a/spec/unit/util_spec.lua b/spec/unit/util_spec.lua new file mode 100644 index 000000000..681d251f5 --- /dev/null +++ b/spec/unit/util_spec.lua @@ -0,0 +1,36 @@ +require("commonrequire") + +local util = require("util") + +describe("util module", function() + it("should strip punctuations around word", function() + assert.is_equal(util.stripePunctuations("\"hello world\""), "hello world") + assert.is_equal(util.stripePunctuations("\"hello world?\""), "hello world") + assert.is_equal(util.stripePunctuations("\"hello, world?\""), "hello, world") + assert.is_equal(util.stripePunctuations("“你好“"), "你好") + assert.is_equal(util.stripePunctuations("“你好?“"), "你好") + end) + it("should split string with patterns", function() + local sentence = "Hello world, welcome to KoReader!" + local words = {} + for word in util.gsplit(sentence, "%s+", false) do + table.insert(words, word) + end + assert.are_same(words, {"Hello", "world,", "welcome", "to", "KoReader!"}) + end) + it("should split command line arguments with quotation", function() + local command = "./sdcv -nj \"words\" \"a lot\" 'more or less' --data-dir=dict" + local argv = {} + for arg1 in util.gsplit(command, "[\"'].-[\"']", true) do + for arg2 in util.gsplit(arg1, "^[^\"'].-%s+", true) do + for arg3 in util.gsplit(arg2, "[\"']", false) do + local trimed = arg3:gsub("^%s*(.-)%s*$", "%1") + if trimed ~= "" then + table.insert(argv, trimed) + end + end + end + end + assert.are_same(argv, {"./sdcv", "-nj", "words", "a lot", "more or less", "--data-dir=dict"}) + end) +end) From d345f21c3960afbeb16ed4e334c821b7b0d4f034 Mon Sep 17 00:00:00 2001 From: chrox Date: Wed, 22 Apr 2015 14:27:05 +0800 Subject: [PATCH 3/3] Fix sdcv on Android cannot handle morphological changes --- .../apps/reader/modules/readerdictionary.lua | 16 +++++++++++----- platform/android/llapp_main.lua | 2 +- platform/android/luajit-launcher | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index a7ab37826..823cd6789 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -70,12 +70,18 @@ function ReaderDictionary:stardictLookup(word, box) word = require("util").stripePunctuations(word) DEBUG("stripped word:", word) -- escape quotes and other funny characters in word - local std_out = io.popen("./sdcv --utf8-input --utf8-output -nj " - .. ("%q"):format(word) .. " --data-dir " .. self.data_dir, "r") local results_str = nil - if std_out then - results_str = std_out:read("*all") - std_out:close() + if Device:isAndroid() then + local A = require("android") + results_str = A.stdout("./sdcv", "--utf8-input", "--utf8-output", + "-nj", word, "--data-dir", self.data_dir) + else + local std_out = io.popen("./sdcv --utf8-input --utf8-output -nj " + .. ("%q"):format(word) .. " --data-dir " .. self.data_dir, "r") + if std_out then + results_str = std_out:read("*all") + std_out:close() + end end --DEBUG("result str:", word, results_str) local ok, results = pcall(JSON.decode, results_str) diff --git a/platform/android/llapp_main.lua b/platform/android/llapp_main.lua index 94f2d12c9..03297cf8a 100644 --- a/platform/android/llapp_main.lua +++ b/platform/android/llapp_main.lua @@ -27,7 +27,7 @@ A.LOGI("intent file path " .. (file or "")) pcall(function() dofile("/sdcard/koreader/patch.lua") end) -- set proper permission for sdcv -io.popen("chmod 755 ./sdcv") +A.execute("chmod", "755", "./sdcv") -- create fake command-line arguments arg = {"-d", file or "/sdcard"} diff --git a/platform/android/luajit-launcher b/platform/android/luajit-launcher index a00e3d1c7..ddcf09b0f 160000 --- a/platform/android/luajit-launcher +++ b/platform/android/luajit-launcher @@ -1 +1 @@ -Subproject commit a00e3d1c7f73756a3c3cf45b1828c2b55a903503 +Subproject commit ddcf09b0f8b60e8e3137b818c973aee3ff76d3f4