Skip to content

Commit

Permalink
Fixed #60; completion fails with multiple slashes.
Browse files Browse the repository at this point in the history
Normalizing paths in generators is problematic; if normalizing happens,
it should happen during match insertion.

Comparing input vs matches needs to advance past adjacent path
separators so that "\\\\" is considered equal to "\".
  • Loading branch information
chrisant996 committed Jan 23, 2021
1 parent f91bf6c commit 9ec9eb1
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 2 deletions.
9 changes: 9 additions & 0 deletions clink/core/include/core/match_wild.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ bool match_wild_impl(const str_iter_impl<T>& _pattern, const str_iter_impl<T>& _
pattern.next();
file.next();
symbol_matched = true;
// Advance past path separators (consider "\\\\" and "\" equal).
assert(path::is_separator(c) == path::is_separator(d));
if (path::is_separator(c))
{
while (path::is_separator(pattern.peek()))
pattern.next();
while (path::is_separator(file.peek()))
file.next();
}
break; }
}

Expand Down
2 changes: 2 additions & 0 deletions clink/core/include/core/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ void refresh_pathext();

void normalise(str_base& in_out, int sep=0);
void normalise(char* in_out, int sep=0);
void normalise_separators(str_base& in_out, int sep=0);
void normalise_separators(char* in_out, int sep=0);
bool is_separator(int c);
const char* next_element(const char* in);
bool get_base_name(const char* in, str_base& out);
Expand Down
11 changes: 11 additions & 0 deletions clink/core/include/core/str_compare.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include "base.h"
#include "path.h"
#include "str_iter.h"

#include <Windows.h>
Expand Down Expand Up @@ -82,6 +83,16 @@ int str_compare_impl(str_iter_impl<T>& lhs, str_iter_impl<T>& rhs)

lhs.next();
rhs.next();

// Advance past path separators (consider "\\\\" and "\" equal).
assert((c == '/') == (d == '/'));
if (c == '/')
{
while (path::is_separator(lhs.peek()))
lhs.next();
while (path::is_separator(rhs.peek()))
rhs.next();
}
}

if (lhs.more() || rhs.more())
Expand Down
2 changes: 1 addition & 1 deletion clink/core/src/globber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ globber::globber(const char* pattern)
m_handle = nullptr;

path::get_directory(pattern, m_root);
path::normalise(m_root.data());
path::normalise_separators(m_root.data());
}

//------------------------------------------------------------------------------
Expand Down
17 changes: 17 additions & 0 deletions clink/core/src/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,23 @@ void normalise(char* in_out, int sep)
*write = '\0';
}

//------------------------------------------------------------------------------
void normalise_separators(str_base& in_out, int sep)
{
normalise_separators(in_out.data(), sep);
}

//------------------------------------------------------------------------------
void normalise_separators(char* in_out, int sep)
{
if (!sep)
sep = PATH_SEP[0];

for (char* next = in_out; *next; next++)
if (is_separator(*next) && *next != sep)
*next = sep;
}

//------------------------------------------------------------------------------
bool is_separator(int c)
{
Expand Down
2 changes: 1 addition & 1 deletion clink/lib/src/file_match_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static class : public match_generator
free(expanded_root);
}

path::normalise(root);
path::normalise_separators(root);

root << "*";

Expand Down
13 changes: 13 additions & 0 deletions clink/lib/test/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,17 @@ TEST_CASE("File match generator")
tester.set_expected_matches("m:only", "m:file1", "m:file2");
tester.run();
}

SECTION("redundant separators")
{
tester.set_input("dir1\\\\\\" DO_COMPLETE);
tester.set_expected_matches("dir1\\only", "dir1\\file1", "dir1\\file2");
tester.set_expected_output("dir1\\");
tester.run();

tester.set_input("dir1\\\\\\f" DO_COMPLETE);
tester.set_expected_matches("dir1\\file1", "dir1\\file2");
tester.set_expected_output("dir1\\file");
tester.run();
}
}

0 comments on commit 9ec9eb1

Please sign in to comment.