Skip to content

Commit

Permalink
Fixed #113; clink.slash_translation() had been removed.
Browse files Browse the repository at this point in the history
This change does several things:
1. Adds back `clink.slash_translation()` API for backward compatibility.
2. Adds new `clink.translateslashes()` API.
3. Adds new `matches.translate_slashes` setting.

The default behavior for built in functionality is the same:  file and
directory matches are translated to use the system path separator
(backslash on Windows).

The default behavior for custom generators has changed:  adding matches
of type 'file' or 'dir' or 'none' (or not specifying type) now applies
the same slash translation as the built in file match generator.

Adding other match types is never affected by any slash translations.

The new `matches.translate_slashes` setting overrides the default slash
translation mode:
- `off` turns off slash translation for custom generators.
- `system` is the behavior described above.
- `slash` translates to forward slashes.
- `backslash` translates to backslashes.

The `clink.translateslashes()` and `clink.slash_translation()` APIs can
override the behavior for the current completion invocation.
  • Loading branch information
chrisant996 committed May 11, 2021
1 parent 539e9f3 commit 3b2d3fb
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 62 deletions.
8 changes: 7 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

## Releases from [chrisant996/clink](https://github.com/chrisant996/clink) fork

### v1.2.7

- Fixed [#113](https://github.com/chrisant996/clink/issues/113); `clink.slash_translation()` had been removed (regression introduced in v1.0.0).
- The new `match.translate_slashes` setting controls the default behavior for slash translation for completion matches.
- The new `clink.translateslashes()` API can override slash translation for completion matches (and `clink.slash_translation()` is supported for backward compatibility).

### v1.2.6

- Fixed tilde expansion for directory by itself; now `~\` can change the working directory to the `~` directory.
- Fixed pagination when displaying completions that take more than 1 line to display.
- Fixed inserting directory match completions when a Lua script didn't include a trailing path separator in the directory match.
- Fixed [#111](https://github.com/chrisant996/clink/issues/111); `..` completion is different from bash.
- Fixed [#111](https://github.com/chrisant996/clink/issues/111); `..` completion is different from bash (regression introduced in v1.0.0).

### v1.2.5

Expand Down
2 changes: 1 addition & 1 deletion clink/app/src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#define CLINK_VERSION_MAJOR 1
#define CLINK_VERSION_MINOR 2
#define CLINK_VERSION_PATCH 6
#define CLINK_VERSION_PATCH 7
#define CLINK_VERSION_STR AS_STR(CLINK_VERSION_MAJOR) ## "." ##\
AS_STR(CLINK_VERSION_MINOR) ## "." ##\
AS_STR(CLINK_VERSION_PATCH) ## "." ##\
Expand Down
4 changes: 2 additions & 2 deletions clink/lib/include/lib/matches.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ class match_builder
{
public:
match_builder(matches& matches);
bool add_match(const char* match, match_type type);
bool add_match(const match_desc& desc);
bool add_match(const char* match, match_type type, bool already_normalised=false);
bool add_match(const match_desc& desc, bool already_normalised=false);
void set_append_character(char append);
void set_suppress_append(bool suppress=true);
void set_suppress_quoting(int suppress=1); //0=no, 1=yes, 2=suppress end quote
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 @@ -79,7 +79,7 @@ static class : public match_generator
{
root.truncate(root_len);
path::append(root, buffer.c_str());
builder.add_match(root.c_str(), to_match_type(st_mode, attr));
builder.add_match(root.c_str(), to_match_type(st_mode, attr), true/*already_normalised*/);
}

return true;
Expand Down
72 changes: 60 additions & 12 deletions clink/lib/src/matches_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "match_generator.h"

#include <core/base.h>
#include <core/settings.h>
#include <core/str.h>
#include <core/str_compare.h>
#include <core/str_tokeniser.h>
Expand All @@ -20,6 +21,25 @@ extern "C" {
extern int rl_complete_with_tilde_expansion;
};

//------------------------------------------------------------------------------
static int s_slash_translation = 0;
void set_slash_translation(int mode) { s_slash_translation = mode; }

//------------------------------------------------------------------------------
static setting_enum g_translate_slashes(
"match.translate_slashes",
"Translate slashes and backslashes",
"File and directory completions can be translated to use consistent slashes.\n"
"The default is 'system' to use the appropriate path separator for the OS host\n"
"(backslashes on Windows). Use 'slash' to use forward slashes, or 'backslash'\n"
"to use backslashes. Use 'off' to turn off translating slashes from custom\n"
"match generators.",
"off,system,slash,backslash",
1
);



//------------------------------------------------------------------------------
match_type to_match_type(int mode, int attr)
{
Expand Down Expand Up @@ -137,20 +157,20 @@ match_builder::match_builder(matches& matches)
}

//------------------------------------------------------------------------------
bool match_builder::add_match(const char* match, match_type type)
bool match_builder::add_match(const char* match, match_type type, bool already_normalised)
{
char suffix = 0;
match_desc desc = {
match,
type
};
return add_match(desc);
return add_match(desc, already_normalised);
}

//------------------------------------------------------------------------------
bool match_builder::add_match(const match_desc& desc)
bool match_builder::add_match(const match_desc& desc, bool already_normalized)
{
return ((matches_impl&)m_matches).add_match(desc);
return ((matches_impl&)m_matches).add_match(desc, already_normalized);
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -529,6 +549,8 @@ void matches_impl::reset()
m_word_break_position = -1;
m_filename_completion_desired.reset();
m_filename_display_desired.reset();

s_slash_translation = g_translate_slashes.get();
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -569,7 +591,7 @@ void matches_impl::set_matches_are_files(bool files)
}

//------------------------------------------------------------------------------
bool matches_impl::add_match(const match_desc& desc)
bool matches_impl::add_match(const match_desc& desc, bool already_normalized)
{
const char* match = desc.match;
match_type type = desc.type;
Expand All @@ -583,20 +605,46 @@ bool matches_impl::add_match(const match_desc& desc)
if (desc.type == match_type::none && ends_with_sep)
type = match_type::dir;

// insert_match() relies on Clink always including a trailing path separator
// on directory matches, so add one if the caller omitted it.
const char* store_match;
// Slash translation happens only for dir, file, and none match types. And
// only when `clink.slash_translation` is enabled. already_normalized means
// desc has already been normalized to system format, and a performance
// optimization can skip translation if system format is configured.
int mode = (s_slash_translation &&
(type == match_type::dir ||
type == match_type::file ||
(type == match_type::none &&
m_filename_completion_desired.get()))) ? s_slash_translation : 0;
bool translate = (mode > 0 && (mode > 1 || !already_normalized));

str<280> tmp;
if (type == match_type::dir && !ends_with_sep)
{
str<32> tmp(match);
// insert_match() relies on Clink always including a trailing path
// separator on directory matches, so add one if the caller omitted it.
tmp = match;
path::append(tmp, "");
store_match = m_store.store_front(tmp.c_str());
match = tmp.c_str();
}
else
else if (translate)
{
tmp = match;
}

if (translate)
{
store_match = m_store.store_front(match);
assert(mode > 0);
int sep;
switch (mode)
{
default: sep = 0; break;
case 2: sep = '/'; break;
case 3: sep = '\\'; break;
}
path::normalise_separators(tmp, sep);
match = tmp.c_str();
}

const char* store_match = m_store.store_front(match);
if (!store_match)
return false;

Expand Down
2 changes: 1 addition & 1 deletion clink/lib/src/matches_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class matches_impl
void set_suppress_append(bool suppress);
void set_suppress_quoting(int suppress);
void set_matches_are_files(bool files);
bool add_match(const match_desc& desc);
bool add_match(const match_desc& desc, bool already_normalised=false);
unsigned int get_info_count() const;
const match_info* get_infos() const;
match_info* get_infos();
Expand Down
5 changes: 4 additions & 1 deletion clink/lua/scripts/arguments.lua
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,10 @@ function _argmatcher:_generate(line_state, match_builder)
-- Select between adding flags or matches themselves. Works in conjunction
-- with getwordbreakinfo()'s return.
if matcher._flags and matcher:_is_flag(line_state:getendword()) then
add_matches(matcher._flags._args[1], match_type)
-- Flags are always "arg" type, which helps differentiate them from
-- filename completions even when using _deprecated matcher mode, so
-- that path normalization can avoid affecting flags like "/c", etc.
add_matches(matcher._flags._args[1], "arg")
return true
else
-- When endword is adjacent the previous word and the previous word ends
Expand Down
Loading

0 comments on commit 3b2d3fb

Please sign in to comment.