Skip to content

Commit c2be029

Browse files
committed
[prompt] try to handle windows paths
1 parent 9efadb1 commit c2be029

13 files changed

Lines changed: 96 additions & 20 deletions

src/base/fs_util.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "itertools.hh"
4646
#include "lnav_log.hh"
4747
#include "opt_util.hh"
48+
#include "pcrepp/pcre2pp.hh"
4849
#include "scn/scan.h"
4950
#include "short_alloc.h"
5051

@@ -147,6 +148,9 @@ escape_path(const std::filesystem::path& p, path_type pt)
147148
case '?':
148149
switch (pt) {
149150
case path_type::normal:
151+
case path_type::windows:
152+
case path_type::remote:
153+
case path_type::url:
150154
retval.push_back('\\');
151155
break;
152156
case path_type::pattern:
@@ -162,6 +166,59 @@ escape_path(const std::filesystem::path& p, path_type pt)
162166
return retval;
163167
}
164168

169+
bool
170+
is_url(const std::string& fn)
171+
{
172+
static const auto url_re
173+
= lnav::pcre2pp::code::from_const("^(file|https?|ftps?|scp|sftp):.*");
174+
175+
return url_re.find_in(fn).ignore_error().has_value();
176+
}
177+
178+
path_type
179+
determine_path_type(const std::string& arg)
180+
{
181+
if (is_glob(arg)) {
182+
return path_type::pattern;
183+
}
184+
185+
if (is_url(arg)) {
186+
return path_type::url;
187+
}
188+
189+
switch (arg.find(':')) {
190+
case 0:
191+
return path_type::normal;
192+
case 1:
193+
return path_type::windows;
194+
default:
195+
return path_type::remote;
196+
}
197+
}
198+
199+
std::filesystem::path
200+
to_posix_path(std::string arg)
201+
{
202+
if (cget(arg, 1).value_or('\0') != ':') {
203+
return {arg};
204+
}
205+
206+
switch (cget(arg, 2).value_or('\0')) {
207+
case '\\':
208+
case '/':
209+
arg.erase(1, 1);
210+
break;
211+
default:
212+
arg[1] = '/';
213+
break;
214+
}
215+
216+
arg.insert(arg.begin(), '/');
217+
std::replace(arg.begin(), arg.end(), '\\', '/');
218+
219+
return {arg};
220+
}
221+
165222
std::pair<std::string, file_location_t>
166223
split_file_location(const std::string& file_path_str)
167224
{

src/base/fs_util.hh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,23 @@ is_glob(const std::string& fn)
6060
|| fn.find('[') != std::string::npos);
6161
}
6262

63+
bool is_url(const std::string& fn);
64+
6365
enum class path_type {
6466
normal,
6567
pattern,
68+
windows,
69+
remote,
70+
url,
6671
};
6772

6873
std::string escape_path(const std::filesystem::path& p,
6974
path_type pt = path_type::normal);
7075

76+
path_type determine_path_type(const std::string& arg);
77+
78+
std::filesystem::path to_posix_path(std::string arg);
79+
7180
std::pair<std::string, file_location_t> split_file_location(
7281
const std::string& path);
7382

src/base/fs_util.tests.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@
3535
#include "config.h"
3636
#include "doctest/doctest.h"
3737

38+
TEST_CASE("fs_util::to_posix_path")
39+
{
40+
CHECK("/c/foo/bar" == lnav::filesystem::to_posix_path("c:\\foo\\bar"));
41+
42+
CHECK("/c/" == lnav::filesystem::to_posix_path("c:"));
43+
44+
CHECK("/c/" == lnav::filesystem::to_posix_path("c:\\"));
45+
46+
// XXX what should this be?
47+
CHECK("/c/foo/bar" == lnav::filesystem::to_posix_path("c:foo\\bar"));
48+
49+
CHECK("" == lnav::filesystem::to_posix_path(""));
50+
}
51+
3852
TEST_CASE("fs_util::build_path")
3953
{
4054
auto* old_path = getenv("PATH");

src/base/humanize.network.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ from_str(string_fragment sf)
4242
{
4343
static const auto REMOTE_PATTERN = lnav::pcre2pp::code::from_const(
4444
"^(?:(?<username>[\\w\\._\\-]+)@)?"
45-
"(?:\\[(?<ipv6>[^\\]]+)\\]|(?<hostname>[^\\[/:]+)):"
45+
"(?:\\[(?<ipv6>[^\\]]+)\\]|(?<hostname>[^\\[/:]{2,})):"
4646
"(?<path>.*)$");
4747
thread_local auto REMOTE_MATCH_DATA = REMOTE_PATTERN.create_match_data();
4848

src/base/string_util.cc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,6 @@ utf8_char_to_byte_index(const std::string& str, ssize_t ch_index)
213213

214214
return retval;
215215
}
216-
bool
217-
is_url(const std::string& fn)
218-
{
219-
static const auto url_re = std::regex("^(file|https?|ftps?|scp|sftp):.*");
220-
221-
return std::regex_match(fn, url_re);
222-
}
223216

224217
size_t
225218
last_word_str(char* str, size_t len, size_t max_len)

src/base/string_util.hh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,6 @@ utf8_string_length(const std::string& str)
207207
return utf8_string_length(str.c_str(), str.length());
208208
}
209209

210-
bool is_url(const std::string& fn);
211-
212210
bool is_blank(const std::string& str);
213211

214212
size_t abbreviate_str(char* str, size_t len, size_t max_len);

src/cmds.io.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ com_open(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
940940
}
941941
#endif
942942

943-
if (is_url(fn.c_str())) {
943+
if (lnav::filesystem::is_url(fn)) {
944944
#ifndef HAVE_LIBCURL
945945
retval = "error: lnav was not compiled with libcurl";
946946
#else
@@ -1502,7 +1502,7 @@ com_close(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
15021502
const auto& fn = fn_v[lpc];
15031503
const auto& actual_path = actual_path_v[lpc];
15041504

1505-
if (is_url(fn.c_str())) {
1505+
if (lnav::filesystem::is_url(fn)) {
15061506
isc::to<curl_looper&, services::curl_streamer_t>().send(
15071507
[fn](auto& clooper) { clooper.close_request(fn); });
15081508
}

src/command_executor.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ execute_file(exec_context& ec, const std::string& path_and_args)
690690
if (iter != scripts.as_scripts.end()) {
691691
paths_to_exec = iter->second;
692692
}
693-
if (is_url(script_name)) {
693+
if (lnav::filesystem::is_url(script_name)) {
694694
auto_mem<CURLU> cu(curl_url_cleanup);
695695
cu = curl_url();
696696
auto set_rc = curl_url_set(cu, CURLUPART_URL, script_name.c_str(), 0);

src/file_collection.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ file_collection::expand_filename(
650650
}
651651
}
652652

653-
if (is_url(path)) {
653+
if (lnav::filesystem::is_url(path)) {
654654
return;
655655
}
656656

src/lnav.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,16 +3580,19 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
35803580
auto_mem<char> abspath;
35813581
struct stat st;
35823582

3583-
auto file_path = std::filesystem::path(
3583+
auto file_path = lnav::filesystem::to_posix_path(
35843584
stat(file_path_without_trailer.c_str(), &st) == 0
35853585
? file_path_without_trailer
35863586
: file_path_str);
35873587

3588+
auto file_path_type
3589+
= lnav::filesystem::determine_path_type(file_path.string());
3590+
35883591
if (file_path_str == "-") {
35893592
load_stdin = true;
35903593
}
35913594
#ifdef HAVE_LIBCURL
3592-
else if (is_url(file_path_str))
3595+
else if (file_path_type == lnav::filesystem::path_type::url)
35933596
{
35943597
auto ul = std::make_shared<url_loader>(file_path_str);
35953598

@@ -3603,12 +3606,12 @@ SELECT tbl_name FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE%'
36033606
fmt::format(FMT_STRING(":open {}"), file_path_str));
36043607
}
36053608
#endif
3606-
else if (lnav::filesystem::is_glob(file_path))
3609+
else if (file_path_type == lnav::filesystem::path_type::pattern)
36073610
{
36083611
lnav_data.ld_active_files.fc_file_names[file_path].with_follow(
36093612
!(lnav_data.ld_flags & LNF_HEADLESS));
36103613
} else if (lnav::filesystem::statp(file_path, &st) == -1) {
3611-
if (file_path_str.find(':') != std::string::npos) {
3614+
if (file_path_type == lnav::filesystem::path_type::remote) {
36123615
lnav_data.ld_active_files.fc_file_names[file_path].with_follow(
36133616
!(lnav_data.ld_flags & LNF_HEADLESS));
36143617
} else {

0 commit comments

Comments
 (0)