Skip to content

Commit

Permalink
Fix case sensitivity when providing completions for paths (#2059)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Wootten authored Feb 23, 2023
1 parent c76f957 commit 9ec58ab
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 58 deletions.
35 changes: 19 additions & 16 deletions libcore/Directory.vala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Files.Directory : Object {
}

public delegate void FileLoadedFunc (Files.File file);
public delegate void DoneLoadingFunc ();

private uint load_timeout_id = 0;
private uint mount_timeout_id = 0;
Expand Down Expand Up @@ -166,7 +167,7 @@ public class Files.Directory : Object {
* to perform filename completion.- Emitting a done_loaded signal in that case would cause
* the premature ending of text entry.
**/
public void init (FileLoadedFunc? file_loaded_func = null) {
public void init (FileLoadedFunc? file_loaded_func = null, DoneLoadingFunc? done_loading_func = null) {
if (state == State.LOADING) {
debug ("Directory Init re-entered - already loading");
return; /* Do not re-enter */
Expand All @@ -180,19 +181,19 @@ public class Files.Directory : Object {

/* If we already have a loaded file cache just list them */
if (previous_state == State.LOADED) {
list_cached_files (file_loaded_func);
list_cached_files (file_loaded_func, done_loading_func);
/* else fully initialise the directory */
} else {
state = State.LOADING;
prepare_directory.begin (file_loaded_func);
prepare_directory.begin (file_loaded_func, done_loading_func);
}
/* done_loaded signal is emitted when ready */
}

/* This is also called when reloading the directory so that another attempt to connect to
* the network is made
*/
private async void prepare_directory (FileLoadedFunc? file_loaded_func) {
private async void prepare_directory (FileLoadedFunc? file_loaded_func, DoneLoadingFunc? done_loading_func) {
debug ("Preparing directory for loading");
/* Force info to be refreshed - the Files.File may have been created already by another part of the program
* that did not ensure the correct info Aync purposes, and retrieved from cache (bug 1511307).
Expand Down Expand Up @@ -228,7 +229,7 @@ public class Files.Directory : Object {
);

/* Only place that should call make_ready function */
yield make_ready (file.is_connected && (is_no_info || success), file_loaded_func);
yield make_ready (is_no_info || success, file_loaded_func, done_loading_func); /* Only place that should call this function */
}

/*** Returns false if should be able to get info but were unable to ***/
Expand Down Expand Up @@ -423,7 +424,7 @@ public class Files.Directory : Object {
}


private async void make_ready (bool ready, FileLoadedFunc? file_loaded_func = null) {
private async void make_ready (bool ready, FileLoadedFunc? file_loaded_func, DoneLoadingFunc? done_loading_func) {
debug ("make ready");
can_load = ready;

Expand All @@ -441,7 +442,7 @@ public class Files.Directory : Object {
file.exists.to_string ());
directory_cache.remove (creation_key);
is_ready = false;
after_loading (file_loaded_func);
after_loading (done_loading_func);
return;
}

Expand Down Expand Up @@ -494,7 +495,7 @@ public class Files.Directory : Object {
connect_volume_monitor_signals ();
}

yield list_directory_async (file_loaded_func);
yield list_directory_async (file_loaded_func, done_loading_func);
}

private void set_confirm_trash () {
Expand Down Expand Up @@ -590,7 +591,7 @@ public class Files.Directory : Object {
}
}

private void list_cached_files (FileLoadedFunc? file_loaded_func = null) {
private void list_cached_files (FileLoadedFunc? file_loaded_func, DoneLoadingFunc? done_loading_func) {
debug ("list cached files");
if (state != State.LOADED) {
critical ("list cached files called in %s state - not expected to happen", state.to_string ());
Expand All @@ -609,10 +610,10 @@ public class Files.Directory : Object {
state = State.LOADED;
loaded_from_cache = true;

after_loading (file_loaded_func);
after_loading (done_loading_func);
}

private async void list_directory_async (FileLoadedFunc? file_loaded_func) {
private async void list_directory_async (FileLoadedFunc? file_loaded_func, DoneLoadingFunc? done_loading_func) {
debug ("list directory async");
/* Should only be called after creation and if reloaded */
if (!is_ready || file_hash.size () > 0) {
Expand Down Expand Up @@ -709,7 +710,7 @@ public class Files.Directory : Object {
} finally {
cancel_timeout (ref load_timeout_id);
loaded_from_cache = false;
after_loading (file_loaded_func);
after_loading (done_loading_func);
}
}

Expand All @@ -725,7 +726,7 @@ public class Files.Directory : Object {
}
}

private void after_loading (FileLoadedFunc? file_loaded_func) {
private void after_loading (DoneLoadingFunc? done_loading_func) {
/* If loading failed reset */
debug ("after loading state is %s", state.to_string ());
if (state == State.LOADING || state == State.TIMED_OUT) {
Expand All @@ -737,8 +738,10 @@ public class Files.Directory : Object {
clear_directory_info ();
}

if (file_loaded_func == null) {
if (done_loading_func == null) {
done_loading ();
} else {
done_loading_func ();
}

if (file.is_directory) { /* Fails for non-existent directories */
Expand Down Expand Up @@ -769,9 +772,9 @@ public class Files.Directory : Object {
return;
}
if (state != State.LOADED) {
list_directory_async.begin (null);
list_directory_async.begin (null, null);
} else {
list_cached_files ();
list_cached_files (null, null);
}
}

Expand Down
96 changes: 54 additions & 42 deletions src/View/Widgets/BreadcrumbsEntry.vala
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ namespace Files.View.Chrome {

/** Completion support **/
Directory? current_completion_dir = null;
string completion_text = "";
bool autocompleted = false;

bool match_found = false;
bool multiple_completions = false;
/* The string which contains the text we search in the file. e.g, if the
* user enter /home/user/a, we will search for "a". */
string to_search = "";
string to_complete = ""; // Beginning of filename to be completed
string completion_text = ""; // Candidate completion (placeholder)
string matching_filename = "";
string common_chars = "";

public bool search_mode = false; // Used to suppress activate events while searching

Expand Down Expand Up @@ -75,8 +76,6 @@ namespace Files.View.Chrome {
/** Overridden Navigatable interface functions **/
/************************************************/
public override bool on_key_press_event (Gdk.EventKey event) {
autocompleted = false;
multiple_completions = false;
uint keyval;
event.get_keyval (out keyval);
switch (keyval) {
Expand Down Expand Up @@ -134,22 +133,26 @@ namespace Files.View.Chrome {
return;
}

to_search = "";
to_complete = "";
/* don't use get_basename (), it will return "folder" for "/folder/" */
int last_slash = txt.last_index_of_char ('/');
if (last_slash > -1 && last_slash < txt.length) {
to_search = txt.slice (last_slash + 1, text.length);
to_complete = txt.slice (last_slash + 1, text.length);
}
if (to_search.length > 0) {
if (to_complete.length > 0) {
do_completion (txt);
} else {
clear_completion ();
}
}

private void do_completion (string path) {
if (path == current_dir_path) {
return; // Nothing typed yet
}

GLib.File? file = FileUtils.get_file_for_path (FileUtils.sanitize_path (path, current_dir_path));
if (file == null || autocompleted) {
if (file == null) {
return;
}

Expand All @@ -161,11 +164,14 @@ namespace Files.View.Chrome {

if (current_completion_dir == null || !file.equal (current_completion_dir.location)) {
current_completion_dir = Directory.from_gfile (file);
current_completion_dir.init (on_file_loaded);
} else if (current_completion_dir != null && current_completion_dir.can_load) {
}

if (current_completion_dir.can_load) {
clear_completion ();
/* Completion text set by on_file_loaded () */
current_completion_dir.init (on_file_loaded);
matching_filename = "";
multiple_completions = false;
match_found = false;
current_completion_dir.init (on_file_loaded, on_done_loading);
}
}

Expand Down Expand Up @@ -228,43 +234,49 @@ namespace Files.View.Chrome {
}

string file_display_name = file.get_display_name ();
if (file_display_name.length > to_search.length) {
if (file_display_name.ascii_ncasecmp (to_search, to_search.length) == 0) {
if (!autocompleted) {
set_completion_text (file_display_name.slice (to_search.length, file_display_name.length));
autocompleted = true;
if (file_display_name.length > to_complete.length) {
if (file_display_name.up ().has_prefix (to_complete.up ())) {
matching_filename = file_display_name;
if (!match_found) {
match_found = true;
common_chars = matching_filename.slice (
to_complete.length, matching_filename.length
);
} else {
string file_complet = file_display_name.slice (to_search.length, file_display_name.length);
string to_add = "";
for (int i = 0; i < int.min (completion_text.length, file_complet.length); i++) {
if (completion_text[i] == file_complet[i]) {
to_add += completion_text[i].to_string ();
multiple_completions = true;
unichar c1 = {}, c2 = {};
int index1 = 0, index2 = common_chars.length - 1;
while (common_chars.get_next_char (ref index1, out c1) &&
matching_filename.get_next_char (ref index2, out c2)) {

if (c1 == c2) {
common_chars += c1.to_string ();
} else {
break;
}
}

set_completion_text (to_add);
multiple_completions = true;
}

string? str = null;
if (text.length >= 1) {
str = text.slice (0, text.length - to_search.length);
}

if (str == null) {
return;
}
}
}
}

/* autocompletion is case insensitive so we have to change the first completed
* parts to the match the filename (if unique match and if the user did not
* deliberately enter an uppercase character).
*/
if (!multiple_completions && !(to_search.down () != to_search)) {
set_text (str + file_display_name.slice (0, to_search.length));
}
private void on_done_loading () {
if (multiple_completions) {
// We do not change the typed characters if there are multiple matches
set_completion_text (common_chars);
} else if (match_found) {
string str = Path.DIR_SEPARATOR_S;
if (text.length >= 1) {
str = text.slice (0, text.length - to_complete.length);
}

// Change the typed characters to the match the filename when only one match.
set_text (str + matching_filename.slice (0, to_complete.length));
set_completion_text (
matching_filename.slice (to_complete.length, matching_filename.length)
);
}
}

Expand Down

0 comments on commit 9ec58ab

Please sign in to comment.