From eec43aaccb3222c838091ac4eb8f8780d921d4cc Mon Sep 17 00:00:00 2001 From: mitchell <70453897+orbitalquark@users.noreply.github.com> Date: Fri, 22 Jan 2021 15:57:13 -0500 Subject: `io.get_project_root()` accepts an optional flag for returning a submodule root. This is for systems like git that have '.git' files (not directories) for submodules under a parent '.git' directory. --- core/file_io.lua | 11 ++++++++--- docs/api.md | 7 +++++-- modules/lua/ta_api | 2 +- modules/lua/ta_tags | 2 +- test/test.lua | 14 ++++++++++++++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/file_io.lua b/core/file_io.lua index f02043b5..2ff36344 100644 --- a/core/file_io.lua +++ b/core/file_io.lua @@ -338,17 +338,22 @@ local vcs = {'.bzr', '.git', '.hg', '.svn', '_FOSSIL_'} -- VCSes are Bazaar, Fossil, Git, Mercurial, and SVN. -- @param path Optional filesystem path to a project or a file contained within -- a project. The default value is the buffer's filename or the current --- working directory. +-- working directory. This parameter may be omitted. +-- @param submodule Optional flag that indicates whether or not to return the +-- root of the current submodule (if applicable). The default value is +-- `false`. -- @return string root or nil -- @name get_project_root -function io.get_project_root(path) +function io.get_project_root(path, submodule) + if type(path) == 'boolean' then path, submodule = nil, path end if not assert_type(path, 'string/nil', 1) then path = buffer.filename or lfs.currentdir() end local dir = path:match('^(.+)[/\\]?') while dir do for i = 1, #vcs do - if lfs.attributes(dir .. '/' .. vcs[i], 'mode') then return dir end + local mode = lfs.attributes(dir .. '/' .. vcs[i], 'mode') + if mode and (submodule or mode == 'directory') then return dir end end dir = dir:match('^(.+)[/\\]') end diff --git a/docs/api.md b/docs/api.md index 7d225a0d..a0a9b2b3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -4376,7 +4376,7 @@ See also: * [`buffer.close`](#buffer.close) -#### `io.get_project_root`(*path*) +#### `io.get_project_root`(*path, submodule*) Returns the root directory of the project that contains filesystem path *path*. @@ -4387,7 +4387,10 @@ Parameters: * *`path`*: Optional filesystem path to a project or a file contained within a project. The default value is the buffer's filename or the current - working directory. + working directory. This parameter may be omitted. +* *`submodule`*: Optional flag that indicates whether or not to return the + root of the current submodule (if applicable). The default value is + `false`. Return: diff --git a/modules/lua/ta_api b/modules/lua/ta_api index 85d9fb97..014f3f73 100644 --- a/modules/lua/ta_api +++ b/modules/lua/ta_api @@ -549,7 +549,7 @@ get_default_fold_display_text view.get_default_fold_display_text(view)\nReturns get_last_child buffer.get_last_child(buffer, line, level)\nReturns the line number of the last line after line number *line* whose fold\nlevel is greater than *level*.\nIf *level* is `-1`, returns the level of *line*.\n@param buffer A buffer.\n@param line The line number in *buffer* of a header line.\n@param level The fold level, or `-1` for the level of *line*. get_lexer buffer.get_lexer(buffer, current)\nReturns the buffer's lexer name.\nIf *current* is `true`, returns the name of the lexer under the caret in\na multiple-language lexer.\n@param buffer A buffer.\n@param current Whether or not to get the lexer at the current caret position\n in multi-language lexers. The default is `false` and returns the parent\n lexer. get_line buffer.get_line(buffer, line)\nReturns the text on line number *line*, including end of line characters.\n@param buffer A buffer.\n@param line The line number in *buffer* to use.\n@return string, number -get_project_root io.get_project_root(path)\nReturns the root directory of the project that contains filesystem path\n*path*.\nIn order to be recognized, projects must be under version control. Recognized\nVCSes are Bazaar, Fossil, Git, Mercurial, and SVN.\n@param path Optional filesystem path to a project or a file contained within\n a project. The default value is the buffer's filename or the current\n working directory.\n@return string root or nil +get_project_root io.get_project_root(path, submodule)\nReturns the root directory of the project that contains filesystem path\n*path*.\nIn order to be recognized, projects must be under version control. Recognized\nVCSes are Bazaar, Fossil, Git, Mercurial, and SVN.\n@param path Optional filesystem path to a project or a file contained within\n a project. The default value is the buffer's filename or the current\n working directory. This parameter may be omitted.\n@param submodule Optional flag that indicates whether or not to return the\n root of the current submodule (if applicable). The default value is\n `false`.\n@return string root or nil get_rule lexer.get_rule(lexer, id)\nReturns the rule identified by string *id*.\n@param lexer The lexer to fetch a rule from.\n@param id The id of the rule to fetch.\n@return pattern get_sel_text buffer.get_sel_text(buffer)\nReturns the selected text.\nMultiple selections are included in order with no delimiters. Rectangular\nselections are included from top to bottom with end of line characters.\nVirtual space is not included.\n@param buffer A buffer.\n@return string, number get_split_table ui.get_split_table()\nReturns a split table that contains Textadept's current split view structure.\nThis is primarily used in session saving.\n@return table of split views. Each split view entry is a table with 4\n fields: `1`, `2`, `vertical`, and `size`. `1` and `2` have values of either\n nested split view entries or the views themselves; `vertical` is a flag\n that indicates if the split is vertical or not; and `size` is the integer\n position of the split resizer. diff --git a/modules/lua/ta_tags b/modules/lua/ta_tags index 09f7071b..d105a598 100644 --- a/modules/lua/ta_tags +++ b/modules/lua/ta_tags @@ -551,7 +551,7 @@ get_default_fold_display_text _HOME/core/.view.luadoc /^function get_default_fol get_last_child _HOME/core/.buffer.luadoc /^function get_last_child(buffer, line, level) end$/;" f class:buffer get_lexer _HOME/core/.buffer.luadoc /^function get_lexer(buffer, current) end$/;" f class:buffer get_line _HOME/core/.buffer.luadoc /^function get_line(buffer, line) end$/;" f class:buffer -get_project_root _HOME/core/file_io.lua /^function io.get_project_root(path)$/;" f class:io +get_project_root _HOME/core/file_io.lua /^function io.get_project_root(path, submodule)$/;" f class:io get_rule _HOME/lexers/lexer.lua /^function M.get_rule(lexer, id)$/;" f class:lexer get_sel_text _HOME/core/.buffer.luadoc /^function get_sel_text(buffer) end$/;" f class:buffer get_split_table _HOME/core/ui.lua /^local get_split_table$/;" f class:ui diff --git a/test/test.lua b/test/test.lua index 8503615d..e3fb296b 100644 --- a/test/test.lua +++ b/test/test.lua @@ -521,6 +521,20 @@ function test_file_io_get_project_root() assert_equal(io.get_project_root(_HOME .. '/core'), _HOME) assert_equal(io.get_project_root(_HOME .. '/core/init.lua'), _HOME) assert_equal(io.get_project_root('/tmp'), nil) + lfs.chdir(cwd) + + -- Test git submodules. + local dir = os.tmpname() + os.remove(dir) + lfs.mkdir(dir) + lfs.mkdir(dir .. '/.git') + lfs.mkdir(dir .. '/foo') + io.open(dir .. '/foo/.git', 'w'):write():close() -- simulate submodule + assert_equal(io.get_project_root(dir .. '/foo/bar.txt'), dir) + io.open_file(dir .. '/foo/bar.txt') + assert_equal(io.get_project_root(true), dir .. '/foo') + buffer:close() + os.execute('rm -r ' .. dir) assert_raises(function() io.get_project_root(1) end, 'string/nil expected, got number') end -- cgit v1.2.3