commit 1803c26d00a8c55dbd14aeb87a17dfcd8a38cb6a
parent a6a8cee2fd9706dbe479cb55a08011cc78ec0ab9
Author: Lou Woell <lou.woell@posteo.de>
Date:   Tue, 16 Sep 2025 01:01:46 +0200

[locate] handle identifiers with trailing ::

Diffstat:
Mcmd/harehelper/+test/locate_test.ha | 46+++++++++++++++++++++++++++++++++++++++-------
Mcmd/harehelper/locate.ha | 41+++++++++++++++++++++++++++++++----------
Mharedoc.el | 4++--
3 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/cmd/harehelper/+test/locate_test.ha b/cmd/harehelper/+test/locate_test.ha @@ -1,8 +1,11 @@ +use bufio; use dirs; use fmt; +use hare::ast; use hare::lex; use hare::module; use hare::parse; +use memio; use os; use strings; @@ -21,9 +24,29 @@ fn loc_test_fn (in: str, out: lex::location) void = { tags = ["linux", "test"], }; - const id = parse::identstr(in)!; + let buf = memio::fixed(strings::toutf8(in)); + let sc = bufio::newscanner(&buf); + defer bufio::finish(&sc); + let lexer = lex::init(&sc, "<string>"); - match(locate_symbol(&ctx, id)) { + let (id, trailing) = match (parse::ident_trailing(&lexer)) { + case parse::error => + return void; + case let r: (ast::ident, bool) => + yield r; + }; + defer ast::ident_free(id); + + let loc: (lex::location | void) = void; + if (!trailing) { + loc = locate_symbol(&ctx, id); + }; + + if(loc is void){ + loc = locate_module(&ctx, id); + }; + + match(loc) { case void => abort(); case let l: lex::location => fmt::errorfln("path: {}, expected: {}", l.path, out.path)!; @@ -47,7 +70,7 @@ fn loc_test_fn (in: str, out: lex::location) void = { @test fn locate_local_func() void = { loc_test_fn("cmd::harehelper::loc_test_fn", lex::location { path = "locate_test.ha", - line = 10, + line = 13, col = 20, ... }); @@ -56,7 +79,7 @@ fn loc_test_fn (in: str, out: lex::location) void = { @test fn locate_global_multiple1 () void = { loc_test_fn("cmd::harehelper::s", lex::location { path = "locate_test.ha", - line = 9, + line = 12, col = 18, ... }); @@ -65,7 +88,7 @@ fn loc_test_fn (in: str, out: lex::location) void = { @test fn locate_global_multiple2 () void = { loc_test_fn("cmd::harehelper::d", lex::location { path = "locate_test.ha", - line = 9, + line = 12, col = 18, ... }); @@ -74,7 +97,7 @@ fn loc_test_fn (in: str, out: lex::location) void = { @test fn locate_const_multiple1 () void = { loc_test_fn("cmd::harehelper::q", lex::location { path = "locate_test.ha", - line = 7, + line = 10, col = 13, ... }); @@ -83,7 +106,7 @@ fn loc_test_fn (in: str, out: lex::location) void = { @test fn locate_const_multiple2 () void = { loc_test_fn("cmd::harehelper::w", lex::location { path = "locate_test.ha", - line = 7, + line = 10, col = 13, ... }); @@ -97,3 +120,12 @@ fn loc_test_fn (in: str, out: lex::location) void = { ... }); }; + +@test fn locate_module_trailing () void = { + loc_test_fn("os::", lex::location { + path = "os", + line = 0, + col = 0, + ... + }); +}; diff --git a/cmd/harehelper/locate.ha b/cmd/harehelper/locate.ha @@ -12,12 +12,14 @@ // You should have received a copy of the GNU General Public License along with // this program. If not, see <https://www.gnu.org/licenses/>. +use bufio; use fmt; use getopt::{command}; use hare::ast; use hare::lex; use hare::module; use hare::parse; +use memio; use os; use path; use strings; @@ -26,32 +28,45 @@ fn locate (cmd: command, ctx: *module::context) void = { if(len(cmd.args) == 0) fmt::fatal("Expected Argument"); - let id = match (parse::identstr(cmd.args[0])) { + let in = memio::fixed(strings::toutf8(cmd.args[0])); + let sc = bufio::newscanner(&in); + defer bufio::finish(&sc); + let lexer = lex::init(&sc, "<string>"); + + let (id, trailing) = match (parse::ident_trailing(&lexer)) { case parse::error => return void; - case let id: ast::ident => - yield id; + case let r: (ast::ident, bool) => + yield r; }; defer ast::ident_free(id); - match (locate_symbol(ctx, id)) { - case void => - return void; + let loc: (lex::location | void) = void; + if (!trailing) { + loc = locate_symbol(ctx, id); + }; + + if(loc is void){ + loc = locate_module(ctx, id); + }; + + + match (loc) { + case void=> void; case let d: lex::location => fmt::printfln("{}:{}:{}", d.path, d.line, d.col)!; free(d.path); }; }; -fn locate_symbol ( +fn locate_module ( ctx: *module::context, id: ast::ident ) (lex::location | void) = { - - // Check if id is a module match (module::find(ctx, id)) { case let e: module::error => module::finish_error(e); + return void; case let r: (str, module::srcset) => defer module::finish_srcset(&r.1); return lex::location { @@ -61,8 +76,14 @@ fn locate_symbol ( off = 0, }; }; +}; + + +fn locate_symbol ( + ctx: *module::context, + id: ast::ident +) (lex::location | void) = { - // else: treat id as having the form namespace::symbol. let ns: module::location = ident_ns(id); // if no namespace prefix is present look for a declaration in the cwd. if (len(id) <= 1) { diff --git a/haredoc.el b/haredoc.el @@ -132,7 +132,7 @@ "Run haredoc with the current word under the cursor and display the results in a new buffer." (interactive) - (let* ((id (string-trim-right (or sign (haredoc/read-module)) "::")) + (let* ((id (or sign (haredoc/read-module))) (components (string-split id "::" t)) (location (haredoc/get-location id)) (location (string-split location ":" t)) @@ -141,7 +141,7 @@ the results in a new buffer." (string-join (butlast components) "::") (car components))) (current-ns (if (f-directory? path) - id + (string-trim-right id "::") parent-ns))) (when haredoc-stack-item (push haredoc-stack-item haredoc-backward-stack)