diff options
| author | ruki <[email protected]> | 2020-01-19 21:43:08 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-01-19 21:43:08 +0800 |
| commit | 382488036184236e17be24ede9cca18ae8af32c5 (patch) | |
| tree | c9ed704cb7ddc3cc95d5f5833086124a4cbf3759 | |
| parent | 7fa954bf793944bdf42175a372277fcd386d62af (diff) | |
| parent | d0b39e229426a336f71a0cc24f6319a47e2ce975 (diff) | |
Merge pull request #669 from OpportunityLiu/tab-complete
Improve tab complete
32 files changed, 481 insertions, 201 deletions
@@ -273,15 +273,15 @@ Please download and install more other plugins from the plugins repository [xmak * [xmake-vscode](https://github.com/xmake-io/xmake-vscode) -<img src="https://raw.githubusercontent.com/tboox/xmake-vscode/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-vscode/master/res/problem.gif" width="650px" /> * [xmake-sublime](https://github.com/xmake-io/xmake-sublime) -<img src="https://raw.githubusercontent.com/tboox/xmake-sublime/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-sublime/master/res/problem.gif" width="650px" /> * [xmake-idea](https://github.com/xmake-io/xmake-idea) -<img src="https://raw.githubusercontent.com/tboox/xmake-idea/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-idea/master/res/problem.gif" width="650px" /> * [xmake.vim](https://github.com/luzhlon/xmake.vim) (third-party, thanks [@luzhlon](https://github.com/luzhlon)) diff --git a/README_zh.md b/README_zh.md index 2390bf72c..1f1ca78f1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -278,15 +278,15 @@ $ xmake l * [xmake-vscode](https://github.com/xmake-io/xmake-vscode) -<img src="https://raw.githubusercontent.com/tboox/xmake-vscode/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-vscode/master/res/problem.gif" width="650px" /> * [xmake-sublime](https://github.com/xmake-io/xmake-sublime) -<img src="https://raw.githubusercontent.com/tboox/xmake-sublime/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-sublime/master/res/problem.gif" width="650px" /> * [xmake-idea](https://github.com/xmake-io/xmake-idea) -<img src="https://raw.githubusercontent.com/tboox/xmake-idea/master/res/problem.gif" width="650px" /> +<img src="https://raw.githubusercontent.com/xmake-io/xmake-idea/master/res/problem.gif" width="650px" /> * [xmake.vim](https://github.com/luzhlon/xmake.vim) (third-party, thanks [@luzhlon](https://github.com/luzhlon)) diff --git a/core/src/demo/xmake.rc b/core/src/demo/xmake.rc index 0b5b17fbe..0d737ebc3 100644 --- a/core/src/demo/xmake.rc +++ b/core/src/demo/xmake.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileDescription", "XMake build utility" VALUE "FileVersion", XM_CONFIG_VERSION "+" STR(XM_CONFIG_VERSION_BUILD) VALUE "InternalName", "xmake" - VALUE "LegalCopyright", "Copyright (C) 2015-2019 Ruki Wang, tboox.org, xmake.io\nCopyright (C) 2005-2015 Mike Pall, luajit.org" + VALUE "LegalCopyright", "Copyright (C) 2015-2020 Ruki Wang, tboox.org, xmake.io\nCopyright (C) 2005-2015 Mike Pall, luajit.org" VALUE "LegalTrademarks", "" VALUE "OriginalFilename", "xmake.exe" VALUE "ProductName", "XMake" diff --git a/core/src/sv/.travis.yml b/core/src/sv/.travis.yml index 505409db5..6b601f3d3 100644 --- a/core/src/sv/.travis.yml +++ b/core/src/sv/.travis.yml @@ -2,7 +2,7 @@ sudo: false language: c before_install: - - bash <(curl -s https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh) + - bash <(curl -s https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/get.sh) install: - xmake diff --git a/scripts/debian/control b/scripts/debian/control index c75388c2d..6230cfb19 100644 --- a/scripts/debian/control +++ b/scripts/debian/control @@ -5,7 +5,7 @@ Maintainer: ruki <[email protected]> Build-Depends: debhelper (>=9) Standards-Version: 3.9.7 Homepage: http://xmake.io -#Vcs-Git: [email protected]:tboox/xmake.git +#Vcs-Git: [email protected]:xmake-io/xmake.git #Vcs-Browser: https://github.com/xmake-io/xmake.git Package: xmake diff --git a/scripts/get.sh b/scripts/get.sh index a0d49c528..fa74379d9 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -143,9 +143,9 @@ if [ 'x__install_only__' != "x$2" ]; then fi # make bytecodes -export XMAKE_PROGRAM_DIR=$projectdir/xmake +XMAKE_PROGRAM_DIR="$projectdir/xmake" \ +XMAKE_ROOT=y \ $projectdir/core/src/demo/demo.b l -v private.utils.bcsave --rootname='@programdir' -x 'scripts/**|templates/**' $projectdir/xmake || my_exit 'generate bytecode failed!' -export XMAKE_PROGRAM_DIR= # do install if [ "$prefix" = "" ]; then diff --git a/scripts/installer.nsi b/scripts/installer.nsi index d5b82e06f..873559961 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -15,16 +15,16 @@ ; xmake version Information !ifndef MAJOR - !define MAJOR 2 + !error 'xmake major version is not defined!' !endif !ifndef MINOR - !define MINOR 2 + !error 'xmake minor version is not defined!' !endif !ifndef ALTER - !define ALTER 9 + !error 'xmake alter version is not defined!' !endif !ifndef BUILD - !define BUILD 201912200000 + !error 'xmake build version is not defined!' !endif !define VERSION ${MAJOR}.${MINOR}.${ALTER} @@ -137,7 +137,7 @@ VIFileVersion ${VERSION}.0 VIAddVersionKey /LANG=0 ProductName XMake VIAddVersionKey /LANG=0 Comments "A cross-platform build utility based on Lua$\nwebsite: https://xmake.io" VIAddVersionKey /LANG=0 CompanyName "The TBOOX Open Source Group" -VIAddVersionKey /LANG=0 LegalCopyright "Copyright (C) 2015-2019 Ruki Wang, tboox.org, xmake.io$\nCopyright (C) 2005-2015 Mike Pall, luajit.org" +VIAddVersionKey /LANG=0 LegalCopyright "Copyright (C) 2015-2020 Ruki Wang, tboox.org, xmake.io$\nCopyright (C) 2005-2015 Mike Pall, luajit.org" VIAddVersionKey /LANG=0 FileDescription "XMake Installer - v${VERSION}" VIAddVersionKey /LANG=0 OriginalFilename "xmake-${ARCH}.exe" VIAddVersionKey /LANG=0 FileVersion ${VERSION_FULL} @@ -232,7 +232,7 @@ Section "XMake (required)" InstallExeutable ; Put file there File /r /x ".DS_Store" /x "*.swp" "..\xmake\*.*" File "..\*.md" - File "..\build\xmake.exe" + File "..\core\build\xmake.exe" File /r /x ".DS_Store" "..\winenv" WriteUninstaller "uninstall.exe" diff --git a/scripts/makeself/header b/scripts/makeself/header index a65aeddf0..0a539e197 100644 --- a/scripts/makeself/header +++ b/scripts/makeself/header @@ -1,5 +1,5 @@ xmake v#xmake-version#, A cross-platform build utility based on Lua -Copyright (C) 2015-2019 Ruki Wang, tboox.org, xmake.io +Copyright (C) 2015-2020 Ruki Wang, tboox.org, xmake.io Copyright (C) 2005-2015 Mike Pall, luajit.org _ __ ___ __ __ __ _| | ______ diff --git a/tests/modules/bytes/test.lua b/tests/modules/bytes/test.lua index 52b754c0a..4cb272c94 100644 --- a/tests/modules/bytes/test.lua +++ b/tests/modules/bytes/test.lua @@ -1,3 +1,4 @@ +import("core.base.bytes") function test_ctor(t) t:are_equal(bytes("123456789"):str(), "123456789") diff --git a/tests/modules/socket/sched_tcp/file_client.lua b/tests/modules/socket/sched_tcp/file_client.lua index 522d05353..311a80eab 100644 --- a/tests/modules/socket/sched_tcp/file_client.lua +++ b/tests/modules/socket/sched_tcp/file_client.lua @@ -1,5 +1,6 @@ import("core.base.socket") import("core.base.scheduler") +import("core.base.bytes") function _session(addr, port) print("connect %s:%d ..", addr, port) diff --git a/tests/modules/socket/tcp/file_client.lua b/tests/modules/socket/tcp/file_client.lua index 42532f5fe..33fde9d09 100644 --- a/tests/modules/socket/tcp/file_client.lua +++ b/tests/modules/socket/tcp/file_client.lua @@ -1,4 +1,5 @@ import("core.base.socket") +import("core.base.bytes") function main() local addr = "127.0.0.1" diff --git a/tests/modules/socket/unix_tcp/file_client.lua b/tests/modules/socket/unix_tcp/file_client.lua index 3f870ae3f..3eadb211e 100644 --- a/tests/modules/socket/unix_tcp/file_client.lua +++ b/tests/modules/socket/unix_tcp/file_client.lua @@ -1,4 +1,5 @@ import("core.base.socket") +import("core.base.bytes") function main(addr) addr = addr or path.join(os.tmpdir(), "file.socket") diff --git a/tests/projects/winsdk/windemo/test b/tests/projects/winsdk/windemo/test index 3988cc4e1..33639f71c 100644 --- a/tests/projects/winsdk/windemo/test +++ b/tests/projects/winsdk/windemo/test @@ -73,7 +73,7 @@ FONT 8, "MS Shell Dlg" BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
- LTEXT "Copyright (C) 2019",IDC_STATIC,42,26,114,8
+ LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
diff --git a/tests/projects/winsdk/windemo/test.rc b/tests/projects/winsdk/windemo/test.rc index 0a595f65f..9ef96ba63 100644 --- a/tests/projects/winsdk/windemo/test.rc +++ b/tests/projects/winsdk/windemo/test.rc @@ -73,7 +73,7 @@ FONT 8, "MS Shell Dlg" BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
- LTEXT "Copyright (C) 2019",IDC_STATIC,42,26,114,8
+ LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
diff --git a/xmake/actions/build/xmake.lua b/xmake/actions/build/xmake.lua index 0eb4eb991..51fd34302 100644 --- a/xmake/actions/build/xmake.lua +++ b/xmake/actions/build/xmake.lua @@ -56,7 +56,7 @@ task("build") , {} , {nil, "target", "v", nil , "The target name. It will build all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/actions/clean/xmake.lua b/xmake/actions/clean/xmake.lua index 1b088c181..0d9b265c1 100644 --- a/xmake/actions/clean/xmake.lua +++ b/xmake/actions/clean/xmake.lua @@ -45,7 +45,7 @@ task("clean") , {} , {nil, "target", "v", nil , "The target name. It will clean all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/actions/config/xmake.lua b/xmake/actions/config/xmake.lua index 8f1f1d06e..6cb5b2247 100644 --- a/xmake/actions/config/xmake.lua +++ b/xmake/actions/config/xmake.lua @@ -78,11 +78,9 @@ task("config") , {'m', "mode", "kv", "release", "Compile for the given mode." , " - debug" , " - release" - , " - ... (custom)" } + , " - ... (custom)" } , {'k', "kind", "kv", "static", "Compile for the given target kind." - , values = function () - return {"static", "shared", "binary"} - end } + , values = {"static", "shared", "binary"} } , {nil, "host", "kv", "$(host)", "The Current Host Environment." } -- show project menu options @@ -131,13 +129,12 @@ task("config") , {category = "Other Configuration"} , {nil, "debugger", "kv", "auto" , "The Debugger" } - , {nil, "ccache", "kv", true , "Enable or disable the c/c++ compiler cache." - , " --ccache=[y|n]" } + , {nil, "ccache", "kv", true , "Enable or disable the c/c++ compiler cache." } , {'o', "buildir", "kv", "build" , "Set the build directory." } , {} , {nil, "target", "v", nil , "Configure for the given target." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/actions/install/xmake.lua b/xmake/actions/install/xmake.lua index 4aad1a62f..09ecc883f 100644 --- a/xmake/actions/install/xmake.lua +++ b/xmake/actions/install/xmake.lua @@ -50,7 +50,7 @@ task("install") , { } , {nil, "target", "v", nil , "The target name. It will install all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/actions/package/xmake.lua b/xmake/actions/package/xmake.lua index d50562ad0..13c3f4b28 100644 --- a/xmake/actions/package/xmake.lua +++ b/xmake/actions/package/xmake.lua @@ -45,7 +45,7 @@ task("package") , {'a', "all", "k", nil , "Package all targets." } , {} , {nil, "target", "v", nil , "The target name. It will package all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/actions/run/xmake.lua b/xmake/actions/run/xmake.lua index 6daf6f328..bfdce3af1 100644 --- a/xmake/actions/run/xmake.lua +++ b/xmake/actions/run/xmake.lua @@ -49,7 +49,21 @@ task("run") " --workdir=`pwd`" } , {} , {nil, "target", "v", nil , "The target name. It will run all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () + return try{ + function () + import("core.project.project") + local targets = project.targets() + local runable = {} + for k, v in pairs(targets) do + if v:script("run") or v:get("kind") == "binary" then + table.insert(runable, k) + end + end + return runable + end + } + end } , {nil, "arguments", "vs", nil , "The target arguments" } } } diff --git a/xmake/actions/uninstall/xmake.lua b/xmake/actions/uninstall/xmake.lua index 511b61e9e..4f70922c2 100644 --- a/xmake/actions/uninstall/xmake.lua +++ b/xmake/actions/uninstall/xmake.lua @@ -52,7 +52,7 @@ task("uninstall") "or $ PREFIX=local xmake uninstall" } , { } , {nil, "target", "v", nil , "The target name. It will uninstall all default targets if this parameter is not specified." - , values = function () return table.keys(import("core.project.project").targets()) end } + , values = function () return try{ function () return table.keys(import("core.project.project").targets()) end } end } } } diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 54343a962..76579ab0f 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -37,7 +37,7 @@ ffi.cdef[[ -- new a bytes instance -- --- bytes(size): allocates a buffer of given size +-- bytes(size[, init]): allocates a buffer of given size, init with given number or char value -- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not) -- bytes(str): mounts a buffer from the given string -- bytes(bytes, start, last): mounts a buffer from another one, with start/last limits @@ -51,9 +51,9 @@ function _instance.new(...) local instance = table.inherit(_instance) if type(arg1) == "number" then local size = arg1 - local ptr = arg2 - if ptr then + if type(arg2) == "cdata" then -- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not) + local ptr = arg2 local manage = arg3 if manage then instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free) @@ -63,8 +63,21 @@ function _instance.new(...) instance._MANAGED = false end else - -- bytes(size): allocates a buffer of given size - ptr = ffi.C.malloc(size) + -- bytes(size[, init]): allocates a buffer of given size + local init + if arg2 then + if type(arg2) == "number" then + init = arg2 + elseif type(arg2) == "string" then + init = arg2:byte() + else + os.raise("invalid arguments #2 for bytes(size, ...), cdata, string, number or nil expected!") + end + end + local ptr = ffi.C.malloc(size) + if init then + ffi.fill(ptr, size, init) + end instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free) instance._MANAGED = true end @@ -429,8 +442,8 @@ end -- register call function setmetatable(bytes, { - __call = function (_, ...) - return bytes.new(...) + __call = function (_, ...) + return bytes.new(...) end, __todisplay = function() return todisplay(bytes.new) diff --git a/xmake/core/base/cli.lua b/xmake/core/base/cli.lua index 5ae476ee1..effa1a0f2 100644 --- a/xmake/core/base/cli.lua +++ b/xmake/core/base/cli.lua @@ -60,10 +60,14 @@ function cli._make_option(key, value, short, argv, argi) return cli._make_segment("option", short and ("-" .. key .. " " .. value) or ("--" .. key .. "=" .. value), argv, argi, { key = key, value = value, short = short or false }) end -function cli.parse(args, ...) - return cli.parsev(os.argv(args), ...) +-- parse a argv string, command & sub-command should be omitted before calling this function +-- @see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html +function cli.parse(args, flags) + return cli.parsev(os.argv(args), flags) end +-- parse a argv array, command & sub-command should be omitted before calling this function +-- @see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html function cli.parsev(argv, flags) local parsed = {} diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index 0b64e6783..103288288 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -24,9 +24,10 @@ local _file = _file or {} local _filelock = _filelock or {} -- load modules -local path = require("base/path") -local table = require("base/table") -local string = require("base/string") +local path = require("base/path") +local table = require("base/table") +local string = require("base/string") +local todisplay = require("base/todisplay") -- save metatable and builtin functions io._file = _file @@ -34,10 +35,10 @@ io._filelock = _filelock io._stdfile = io._stdfile or io.stdfile -- new an file -function _file.new(filepath, fileref) +function _file.new(filepath, fileref, isstdfile) local file = table.inherit(_file) file._NAME = path.filename(filepath) - file._PATH = path.absolute(filepath) + file._PATH = isstdfile and filepath or path.absolute(filepath) file._FILE = fileref setmetatable(file, _file) return file @@ -79,6 +80,30 @@ function _file:__tostring() return "<file: " .. str .. ">" end +-- todisplay(file) +function _file:__todisplay() + local size = _file.size(self) + local filepath = _file.path(self) + if not size then + return string.format("file${reset} %s", todisplay(filepath)) + end + + local unit = "B" + if size >= 1000 then + size = size / 1024 + unit = "KiB" + end + if size >= 1000 then + size = size / 1024 + unit = "MiB" + end + if size >= 1000 then + size = size / 1024 + unit = "GiB" + end + return string.format("file${reset}(${color.dump.number}%.3f%s${reset}) %s", size, unit, todisplay(filepath)) +end + -- gc(file) function _file:__gc() if self._FILE and io.file_close(self._FILE) then @@ -88,7 +113,7 @@ end -- get file length function _file:__len() - return self:size() + return _file.size(self) end -- get file rawfd @@ -223,9 +248,9 @@ end function _file:lines(opt) opt = opt or {} return function() - local l = self:read("l", opt) + local l = _file.read(self, "l", opt) if not l and opt.close_on_finished then - self:close() + _file.close(self) end return l end @@ -233,12 +258,12 @@ end -- print file function _file:print(...) - return self:write(string.format(...), "\n") + return _file.write(self, string.format(...), "\n") end -- printf file function _file:printf(...) - return self:write(string.format(...)) + return _file.write(self, string.format(...)) end -- save object @@ -247,13 +272,13 @@ function _file:save(object, opt) if errors then return false, errors else - return self:write(str) + return _file.write(self, str) end end -- load object function _file:load() - local data, err = self:read("*all") + local data, err = _file.read(self, "*all") if err then return nil, err end @@ -273,12 +298,12 @@ function _filelock.new(lockpath, lock) return filelock end --- get the filelock name +-- get the filelock name function _filelock:name() return self._NAME end --- get the filelock path +-- get the filelock path function _filelock:path() return self._PATH end @@ -384,13 +409,19 @@ end -- tostring(filelock) function _filelock:__tostring() - local str = self:path() + local str = _filelock.path(self) if #str > 16 then str = ".." .. str:sub(#str - 16, #str) end return "<filelock: " .. str .. ">" end +-- todisplay(filelock) +function _filelock:__todisplay() + local str = _filelock.path(self) + return "filelock${reset} " .. todisplay(str) +end + -- gc(filelock) function _filelock:__gc() if self._LOCK and io.filelock_close(self._LOCK) then @@ -498,7 +529,7 @@ function io.stdfile(filepath) file = io._stdfile(3) end if file then - return _file.new(filepath, file) + return _file.new(filepath, file, true) else return nil, string.format("failed to get std file: %s", filepath) end diff --git a/xmake/core/base/option.lua b/xmake/core/base/option.lua index 36bcf6c39..4fa61ad12 100644 --- a/xmake/core/base/option.lua +++ b/xmake/core/base/option.lua @@ -55,6 +55,12 @@ function option._translate(menu) return true end +function option._modenarrow() + -- show menu in narrow mode? + local width = os.getwinsize().width + return width > 0 and width < 60 +end + -- get the top context function option._context() @@ -609,6 +615,8 @@ function option.show_main() -- print tasks if main.tasks then + local narrow = option._modenarrow() + -- make task categories local categories = {} for taskname, taskinfo in pairs(main.tasks) do @@ -651,7 +659,7 @@ function option.show_main() for taskname, taskinfo in pairs(category.tasks) do -- init the task line - local taskline = string.format(" %s%s", + local taskline = string.format(narrow and " %s%s" or " %s%s", taskinfo.shortname and (taskinfo.shortname .. ", ") or " ", taskname) table.insert(tablecontent, {taskline, taskinfo.description or ""}) @@ -661,7 +669,7 @@ function option.show_main() -- set table styles tablecontent.style = {"${color.menu.main.task.name}"} tablecontent.width = {nil, "auto"} - tablecontent.sep = " " + tablecontent.sep = narrow and " " or " " -- print table io.write(text.table(tablecontent)) @@ -697,6 +705,9 @@ function option.show_options(options, taskname) end end + -- narrow mode? + local narrow = option._modenarrow() + -- print header local tablecontent = {} table.insert(tablecontent, {}) @@ -723,48 +734,49 @@ function option.show_options(options, taskname) table.insert(tablecontent, {}) else - -- init the option info - local option_info - -- append the shortname local shortname = opt[1] local name = opt[2] local mode = opt[3] local default = opt[4] + + local title1, title2 + local kvplaceholder = mode == "kv" and ((type(default) == "boolean") and "[y|n]" or(name and name:upper() or "XXX")) if shortname then if mode == "kv" then - option_info = " -" .. shortname .. " " .. (name and name:upper() or "XXX") + title1 = "-" .. shortname .. " " .. kvplaceholder else - option_info = " -" .. shortname + title1 = "-" .. shortname end - else - option_info = " " end -- append the name if name then - local leading = (shortname and "," or " ") .. (mode:startswith("k") and " --" or " ") + local leading = mode:startswith("k") and "--" or " " local kv - if mode:startswith("k") then + if mode == "k" then kv = name + elseif mode == "kv" then + kv = name .. "=" .. kvplaceholder elseif mode == "vs" then kv = name .. " ..." else - kv = (name .. "=" .. ((type(default) == "boolean") and "[y|n]" or name:upper())) + kv = name end - option_info = option_info .. leading .. kv + title2 = leading .. kv elseif mode == "v" or mode == "vs" then - option_info = option_info .. " ..." + title2 = " ..." end -- get description - local description = table.move(opt, 5, table.maxn(opt), 1, {}) + local optdespn = table.maxn(opt) + local description = table.move(opt, 5, optdespn, 1, table.new(optdespn - 5 + 1, 0)) if #description == 0 then description[1] = "" end -- transform description - local desp_strs = {} + local desp_strs = table.new(#description, 0) for _, v in ipairs(description) do if type(v) == "function" then v = v() @@ -787,25 +799,37 @@ function option.show_options(options, taskname) end -- append values - local values, ok = opt.values + local values = opt.values if type(values) == "function" then - ok, values = pcall(values) + values = values() end - if ok and values then + if values then for _, value in ipairs(table.wrap(values)) do table.insert(desp_strs, " - " .. tostring(value)) end end -- insert row - table.insert(tablecontent, {option_info, desp_strs}) + if narrow then + if title1 then + table.insert(tablecontent, {{" " .. title1, " " .. title2 }, desp_strs}) + else + table.insert(tablecontent, {{" " .. title2 }, desp_strs}) + end + else + if title1 then + table.insert(tablecontent, {" " .. title1 .. ", " .. title2 , desp_strs}) + else + table.insert(tablecontent, {" " .. title2 , desp_strs}) + end + end end end -- set table styles tablecontent.style = {"${color.menu.option.name}"} tablecontent.width = {nil, "auto"} - tablecontent.sep = " " + tablecontent.sep = narrow and " " or " " -- print table io.write(text.table(tablecontent)) diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua index 328bd9f6c..04e258b95 100644 --- a/xmake/core/base/table.lua +++ b/xmake/core/base/table.lua @@ -25,6 +25,29 @@ local table = table or {} table.clear = require("table.clear") table.new = require("table.new") +-- move values of table(a1) to table(a2) +-- +-- disable the builtin implementation for android termux/arm64, it will crash when calling `table.move({1, 1}, 1, 2, 1, {})` +-- +-- @see https://github.com/xmake-io/xmake/pull/667#issuecomment-575859604 +-- +if xmake._ARCH:startswith("arm") then + function table.move(a1, f, e, t, a2) + if a2 == nil then a2 = a1 end + assert(a1) + assert(a2) + if e >= f then + local d = t - f + if t > e or t <= f or a2 ~= a1 then + for i = f, e do a2[i + d] = a1[i] end + else + for i = e, f, -1 do a2[i + d] = a1[i] end + end + end + return a2 + end +end + -- join all objects and tables function table.join(...) @@ -348,26 +371,5 @@ function table.reverse(arr) return revarr end --- move values of table(a1) to table(a2) --- --- disable the builtin implementation for android termux/arm64, it will crash when calling `table.move({1, 1}, 1, 2, 1, {})` --- --- @see https://github.com/xmake-io/xmake/pull/667#issuecomment-575859604 --- -if xmake._ARCH:startswith("arm") then - function table.move(a1, f, e, t, a2) - if a2 == nil then a2 = a1 end - if e >= f then - local d = t - f - if t > e or t <= f or a2 ~= a1 then - for i = f, e do a2[i + d] = a1[i] end - else - for i = e, f, -1 do a2[i + d] = a1[i] end - end - end - return a2 - end -end - -- return module: table return table diff --git a/xmake/core/base/text.lua b/xmake/core/base/text.lua index dad69fc86..83b2a229a 100644 --- a/xmake/core/base/text.lua +++ b/xmake/core/base/text.lua @@ -25,7 +25,101 @@ local text = text or {} local string = require("base/string") local colors = require("base/colors") local math = require("base/math") -local dump = require("base/dump") +local table = require("base/table") + + +function text._iswbr(ch) + if not text._CHARWBR then + text._CHARWBR = { + [(' '):byte()] = 100, + [('\n'):byte()] = 100, + [('\t'):byte()] = 100, + [('\v'):byte()] = 100, + [('\f'):byte()] = 100, + [('\r'):byte()] = 100, + [('-'):byte()] = 90, + [(')'):byte()] = 50, + [(']'):byte()] = 50, + [('}'):byte()] = 50, + [(','):byte()] = 50, + [('='):byte()] = 40, + [('|'):byte()] = 40, + } + end + return text._CHARWBR[ch] or false +end + +function text._charwidth(ch) + if ch == 0x09 then + -- TAB + return 4 + elseif ch == 0x08 then + -- BS + return -1 + elseif ch <= 0x1F or ch == 0x7F then + -- other control chars + return 0 + else + return 1 + end +end + +function text._nextwbr(self, iter) + local ptr = iter.pos + 1 + local width = iter.width + local str = self.str + local e = self.j + + if ptr > e then + return nil + end + + while ptr <= e do + local byte = str:byte(ptr) + + -- ansi sequence, skip it + if byte == 27 and ptr + 2 <= e and str:byte(ptr + 1) == 91 then + local ansiend = false + ptr = ptr + 2 + while ptr <= e do + local b = str:byte(ptr) + if b == 109 then + ansiend = true + break + end + ptr = ptr + 1 + end + if not ansiend then + -- ansi sequence not finished in [i, j], no more wbr in the range + return nil + end + else + width = width + text._charwidth(byte) + local wbr = text._iswbr(byte) + if wbr then + return { pos = ptr, width = width, quality = wbr } + end + end + ptr = ptr + 1 + end + + -- wbr at end of string + return { pos = e, width = width, quality = 100 } +end + +function text._iterwbr(str, i, j, wordbreak) + if not i then + i = 1 + elseif i < 0 then + i = #str + 1 + i + end + if not j then + j = #str + elseif j < 0 then + j = #str + 1 + j + end + return text._nextwbr, { str = str, i = i, j = j, wordbreak = wordbreak }, { pos = i - 1, width = 0 } +end -- @see https://unicode.org/reports/tr14/ function text._lastwbr(str, width, wordbreak) @@ -38,21 +132,27 @@ function text._lastwbr(str, width, wordbreak) return width else - if str:sub(width + 1, width + 1):find("[%s]") then + if (text._iswbr(str:byte(width + 1)) or -1) >= 100 then -- exact break return width end - local range = str:sub(1, width) - local poss = range:reverse():find("[%s-]") - if poss then - return #range - poss + 1 + local wbr_candidate + for wbr in text._iterwbr(str, 1, #str, wordbreak) do + if not wbr_candidate then + -- not candidate yet? always use a wbr + wbr_candidate = wbr + elseif (wbr.quality >= wbr_candidate.quality or wbr.quality >= 80) and wbr.width <= width then + -- in range, replace with a higher quality wbr + wbr_candidate = wbr + end + if wbr.width > width then + break + end end - -- not found in range, try afterwards - poss = str:find("[%s-]", width + 1) - if poss then - return poss + if wbr_candidate then + return wbr_candidate.pos end -- not found in all str @@ -71,7 +171,7 @@ function text.wordwrap(str, width, opt) end local lines = tostring(str):split("\n", {plain = true, strict = true}) - local result = {} + local result = table.new(#lines, 0) local actual_width = 0 -- handle lines @@ -110,7 +210,7 @@ function text.wordwrap(str, width, opt) end function text._format_cell(cell, width, opt) - local result = {} + local result = table.new(#cell, 0) local max_width = 0 for _, v in ipairs(cell) do local lines, aw = text.wordwrap(tostring(v), width[2], opt) @@ -165,7 +265,7 @@ function text.table(data, opt) opt.patch_reset = false -- col ordered cells - local cols = {} + local cols = table.new(1, 0) local n_row = table.maxn(data) local n_col = 1 @@ -193,7 +293,7 @@ function text.table(data, opt) end local col = cols[j] if not col then - col = {} + col = table.new(n_row, 0) cols[j] = col end if cell then @@ -206,21 +306,21 @@ function text.table(data, opt) end -- load column options - data.width = data.width or {} - data.align = data.align or {} - data.style = data.style or {} + data.width = data.width or table.new(n_col, 0) + data.align = data.align or table.new(n_col, 0) + data.style = data.style or table.new(n_col, 0) local style = "" if type(data.style) == "string" then style = data.style - data.style = {} + data.style = table.new(n_col, 0) data.sep = style .. data.sep .. "${reset}" end local align = "l" if type(data.align) == "string" then align = data.align - data.align = {} + data.align = table.new(n_col, 0) end local sep = colors.translate(data.sep, opt) @@ -305,12 +405,12 @@ function text.table(data, opt) -- render cells -- row ordered cells - local rows = {} + local rows = table.new(n_row, 0) -- reorder for i = 1, n_row do local d_row = data[i] or {} - local row = {} + local row = table.new(n_col, 0) local line = 1 for j = 1, n_col do local cell = cols[j][i] @@ -333,11 +433,11 @@ function text.table(data, opt) rows[i] = row end - local results = {} + local results = table.new(n_row, 0) local reset = colors.translate("${reset}", opt) for i, row in ipairs(rows) do for l = 1, row.line do - local cells = {} + local cells = table.new(n_col, 0) local j = 1 while j <= n_col do diff --git a/xmake/core/base/todisplay.lua b/xmake/core/base/todisplay.lua index 1a2d59d43..ed821e2f2 100644 --- a/xmake/core/base/todisplay.lua +++ b/xmake/core/base/todisplay.lua @@ -42,7 +42,7 @@ end -- print number function todisplay._print_number(num) - return string.format("${reset}${color.dump.number}%g${reset}", num) + return string.format("${reset}${color.dump.number}%s${reset}", num) end -- print function @@ -70,7 +70,7 @@ function todisplay._print_default_scalar(value, style, formatkey) formatkey = nil end elseif __tostring then - local ok, str = pcall(__todisplay, value) + local ok, str = pcall(__tostring, value) if ok then value = str end diff --git a/xmake/core/main.lua b/xmake/core/main.lua index 1078175d6..bc8bc04b5 100644 --- a/xmake/core/main.lua +++ b/xmake/core/main.lua @@ -27,6 +27,7 @@ local log = require("base/log") local path = require("base/path") local utils = require("base/utils") local option = require("base/option") +local table = require("base/table") local global = require("base/global") local deprecated = require("base/deprecated") local privilege = require("base/privilege") @@ -123,7 +124,7 @@ function main._basicparse() if xmake._ARGV[1] and not xmake._ARGV[1]:startswith('-') then -- regard it as command name xmake._COMMAND = xmake._ARGV[1] - xmake._COMMAND_ARGV = table.move(xmake._ARGV, 2, #xmake._ARGV, 1, {}) + xmake._COMMAND_ARGV = table.move(xmake._ARGV, 2, #xmake._ARGV, 1, table.new(#xmake._ARGV - 1, 0)) else xmake._COMMAND_ARGV = xmake._ARGV end diff --git a/xmake/core/sandbox/modules/bytes.lua b/xmake/core/sandbox/modules/import/core/base/bytes.lua index 261829e92..edee99365 100644 --- a/xmake/core/sandbox/modules/bytes.lua +++ b/xmake/core/sandbox/modules/import/core/base/bytes.lua @@ -11,7 +11,7 @@ -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --- +-- -- Copyright (C) 2015-2020, TBOOX Open Source Group. -- -- @author ruki diff --git a/xmake/modules/devel/git/clone.lua b/xmake/modules/devel/git/clone.lua index 165b6dcbc..027cc9317 100644 --- a/xmake/modules/devel/git/clone.lua +++ b/xmake/modules/devel/git/clone.lua @@ -31,8 +31,8 @@ import("lib.detect.find_tool") -- -- import("devel.git") -- --- git.clone("[email protected]:tboox/xmake.git") --- git.clone("[email protected]:tboox/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"}) +-- git.clone("[email protected]:xmake-io/xmake.git") +-- git.clone("[email protected]:xmake-io/xmake.git", {depth = 1, branch = "master", outputdir = "/tmp/xmake"}) -- -- @endcode -- diff --git a/xmake/modules/private/utils/complete.lua b/xmake/modules/private/utils/complete.lua index 70c54e056..71c7e9fa3 100644 --- a/xmake/modules/private/utils/complete.lua +++ b/xmake/modules/private/utils/complete.lua @@ -21,12 +21,11 @@ -- imports import("core.base.option") import("core.base.task") +import("core.base.cli") -local use_spaces = true local raw_words = {} -local word = "" local position = 0 -local has_space = false +local use_spaces = true local reenter = false function _print_candidate(is_complate, ...) @@ -64,76 +63,163 @@ function _complete_task(tasks, name) return has_candidate end -function _complete_option(options, segs, name) - local current_options = try - { - function() - return option.raw_parse(segs, options, { populate_defaults = false, allow_unknown = true }) +function _complete_option_kv(options, current, completing) + + local name, value + if completing == "-" or completing == "--" then + name = "" + elseif completing:startswith("--") then + local parg = cli.parsev({completing})[1] + if parg.type == "option" then + name, value = parg.key, parg.value + elseif parg.type == "flag" then + name = parg.key end - } - -- current options is invalid - if not current_options then return end + elseif completing:startswith("-") then + -- search full names only + return true + end - -- current context is wrong - if not reenter and (current_options.file or current_options.project) then - local args = {"lua", "--root", "private.utils.complete", tostring(position), use_spaces and "reenter" or "nospace-reenter", table.unpack(raw_words) } - if current_options.file then - table.insert(args, 3, "--file=" .. current_options.file) + if value then + -- complete values + + -- find completion option + local opt + for _, v in ipairs(options) do + if v[3] == "kv" and (v[1] == name or v[2] == name) then + opt = v + break + end end - if current_options.project then - table.insert(args, 3, "--project=" .. current_options.project) + if not opt then + return false end - os.execv("xmake", args) - return - end - local state = 0 - if name == "-" or name == "--" then - name = "" - elseif name:startswith("--") then - state = 2 - name = name:sub(3) - elseif name:startswith("-") then - state = 1 - name = name:sub(2) + -- show candidates of values + local values = opt.values + if type(values) == "function" then + values = values(value) + end + if values == nil and type(opt[4]) == "boolean" then + values = { "y", "n" } + -- ignore existing input + value = "" + end + for _, v in ipairs(values) do + if tostring(v):startswith(value) then + _print_candidate(true, "--%s=%s", name, v) + end + end + return true end - -- search full names only - if name == "" then state = 2 end - - local opcandi = {} + local opcandi = table.new(10, 0) for _, v in ipairs(options) do - if current_options[v[2]] == nil then + if current[v[2]] == nil then if v[3] == "kv" or v[3] == "k" then table.insert(opcandi, v) end end end for _, v in ipairs(opcandi) do - if (state == 2 or state == 0) and v[2]:startswith(name) then + -- startswith + if v[2]:startswith(name) then _print_candidate((v[3] == "k"), (v[3] == "k") and "--%s" or "--%s=", v[2]) - elseif (state == 1 or state == 0) and v[1] and v[1]:startswith(name) then - _print_candidate(true, "-%s", v[1]) end end if name == "" then - return + return true end for _, v in ipairs(opcandi) do -- not startswith - if (state == 2 or state == 0) and v[2]:find(name, 2, true) then + if v[2]:find(name, 2, true) then _print_candidate((v[3] == "k"), (v[3] == "k") and "--%s" or "--%s=", v[2]) - elseif (state == 1 or state == 0) and v[1] and v[1]:find(name, 2, true) then - _print_candidate(true, "-%s", v[1]) end end + + return true end -function _complete() +function _complete_option_v(options, current, completing) + -- find completion option + local opt + local optvs + for _, v in ipairs(options) do + if v[3] == "v" and current[v[2] or v[1]] == nil then + opt = v + end + if v[3] == "vs" and not optvs then + optvs = v + end + end + + if opt then + -- show candidates of values + local values = opt.values + if type(values) == "function" then + values = values(completing) + end + for _, v in ipairs(values) do + if tostring(v):startswith(completing) then + _print_candidate(true, "%s", v) + end + end + return true + end - local tasks = {} - local shortnames = {} + if optvs then + + -- show candidates of values + local values = optvs.values + if type(values) == "function" then + values = values(completing) + end + for _, v in ipairs(values) do + if tostring(v):startswith(completing) then + _print_candidate(true, "%s", v) + end + end + return true + end + + return false +end + +function _complete_option(options, segs, completing) + local current_options = try + { + function() + return option.raw_parse(segs, options, { populate_defaults = false, allow_unknown = true }) + end + } + -- current options is invalid + if not current_options then return false end + + -- current context is wrong + if not reenter and (current_options.file or current_options.project) then + local args = {"lua", "--root", "private.utils.complete", tostring(position), use_spaces and "reenter" or "nospace-reenter", table.unpack(raw_words) } + if current_options.file then + table.insert(args, 3, "--file=" .. current_options.file) + end + if current_options.project then + table.insert(args, 3, "--project=" .. current_options.project) + end + os.execv("xmake", args) + return true + end + + if completing:startswith("-") then + return _complete_option_kv(options, current_options, completing) + else + return _complete_option_v(options, current_options, completing) + end +end + +function _complete(argv, completing) + + local tasks = table.new(10, 0) + local shortnames = table.new(0, 10) for _, v in ipairs(task.names()) do local menu = option.taskmenu(v) tasks[v] = menu @@ -142,34 +228,30 @@ function _complete() end end - if word:lower() == "xmake" then - _complete_task(tasks, "") - return + if #argv == 0 then + if _complete_task(tasks, completing) then return end end - local segs = word:split("%s") - local task_name = table.remove(segs, 1) or "" - - if #segs == 0 and not has_space then - if _complete_task(tasks, task_name) then return end + local task_name = "build" + if argv[1] and not argv[1]:startswith("-") then + task_name = table.remove(argv, 1) end if shortnames[task_name] then task_name = shortnames[task_name] end - if not tasks[task_name] then - table.insert(segs, 1, task_name) - task_name = "run" - end - local incomplete_option = has_space and "" or segs[#segs] - if not has_space then segs[#segs] = nil end + local options + if tasks[task_name] then + options = tasks[task_name].options + else + options = tasks["build"].options + end - _complete_option(tasks[task_name].options, segs, incomplete_option) + _complete_option(options, argv, completing) end function main(pos, config, ...) raw_words = {...} - local words = {...} local is_config = false if config:find("nospace", 1, true) then @@ -182,24 +264,32 @@ function main(pos, config, ...) end if not is_config then - table.insert(words, 1, config) + table.insert(raw_words, 1, config) end - word = table.concat(words, " ") or "" + local word = table.concat(raw_words, " ") or "" position = tonumber(pos) or 0 - has_space = word:endswith(" ") or position > #word + local has_space = word:endswith(" ") or position > #word word = word:trim() - -- normailize word to "xmake ..." - if is_host("windows") then - if word:lower():startswith("xmake.exe") then - word = "xmake" .. word:sub(#"xmake.exe" + 1) + local argv = os.argv(word) + + if argv[1] then + + -- normailize word to remove "xmake" + if is_host("windows") and argv[1]:lower() == "xmake.exe" then + argv[1] = "xmake" + end + if argv[1] == "xmake" then + table.remove(argv, 1) end end - if word:lower():startswith("xmake ") then - word = word:sub(#"xmake " + 1) + if has_space then + _complete(argv, "") + else + local completing = table.remove(argv) + _complete(argv, completing or "") end +end - _complete() -end
\ No newline at end of file |
