aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--misc/bash/completion.sh2
-rw-r--r--src/libcmd/installables.cc4
-rw-r--r--src/libutil/args.cc7
-rw-r--r--src/libutil/util.cc11
-rw-r--r--src/libutil/util.hh3
5 files changed, 21 insertions, 6 deletions
diff --git a/misc/bash/completion.sh b/misc/bash/completion.sh
index 045053dee..9af695f5a 100644
--- a/misc/bash/completion.sh
+++ b/misc/bash/completion.sh
@@ -15,7 +15,7 @@ function _complete_nix {
else
COMPREPLY+=("$completion")
fi
- done < <(NIX_GET_COMPLETIONS=$cword "${words[@]/#\~/$HOME}" 2>/dev/null)
+ done < <(NIX_GET_COMPLETIONS=$cword "${words[@]}" 2>/dev/null)
__ltrim_colon_completions "$cur"
}
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index c4fefb971..a0b8d0af5 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -1,4 +1,5 @@
#include "installables.hh"
+#include "util.hh"
#include "command.hh"
#include "attr-path.hh"
#include "common-eval-args.hh"
@@ -256,8 +257,7 @@ void completeFlakeRefWithFragment(
auto fragment = prefix.substr(hash + 1);
auto flakeRefS = std::string(prefix.substr(0, hash));
- // FIXME: do tilde expansion.
- auto flakeRef = parseFlakeRef(flakeRefS, absPath("."));
+ auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath("."));
auto evalCache = openEvalCache(*evalState,
std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)));
diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index b60c609a6..10f01af5b 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -282,12 +282,13 @@ static void _completePath(std::string_view prefix, bool onlyDirs)
{
completionType = ctFilenames;
glob_t globbuf;
- int flags = GLOB_NOESCAPE | GLOB_TILDE;
+ int flags = GLOB_NOESCAPE;
#ifdef GLOB_ONLYDIR
if (onlyDirs)
flags |= GLOB_ONLYDIR;
#endif
- if (glob((std::string(prefix) + "*").c_str(), flags, nullptr, &globbuf) == 0) {
+ // using expandTilde here instead of GLOB_TILDE(_CHECK) so that ~<Tab> expands to /home/user/
+ if (glob((expandTilde(prefix) + "*").c_str(), flags, nullptr, &globbuf) == 0) {
for (size_t i = 0; i < globbuf.gl_pathc; ++i) {
if (onlyDirs) {
auto st = stat(globbuf.gl_pathv[i]);
@@ -295,8 +296,8 @@ static void _completePath(std::string_view prefix, bool onlyDirs)
}
completions->add(globbuf.gl_pathv[i]);
}
- globfree(&globbuf);
}
+ globfree(&globbuf);
}
void completePath(size_t, std::string_view prefix)
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index deaa17a7f..d9db24397 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -200,6 +200,17 @@ std::string_view baseNameOf(std::string_view path)
}
+std::string expandTilde(std::string_view path)
+{
+ // TODO: expand ~user ?
+ auto tilde = path.substr(0, 2);
+ if (tilde == "~/" || tilde == "~")
+ return getHome() + std::string(path.substr(1));
+ else
+ return std::string(path);
+}
+
+
bool isInDir(std::string_view path, std::string_view dir)
{
return path.substr(0, 1) == "/"
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 94ae8ab7d..a1d0e0e6b 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -68,6 +68,9 @@ Path dirOf(const PathView path);
following the final `/' (trailing slashes are removed). */
std::string_view baseNameOf(std::string_view path);
+/* Perform tilde expansion on a path. */
+std::string expandTilde(std::string_view path);
+
/* Check whether 'path' is a descendant of 'dir'. Both paths must be
canonicalized. */
bool isInDir(std::string_view path, std::string_view dir);