Implement more option for panel filter:

"Files only", "Case sensitive", and "Using shell patterns".

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2022-04-10 16:59:37 +03:00
parent f20f5cc5cb
commit a705b67288
4 changed files with 87 additions and 45 deletions

View File

@ -6,7 +6,7 @@
Written by:
Slava Zanko <slavazanko@gmail.com>, 2013
Andrew Borodin <aborodin@vmail.ru>, 2013
Andrew Borodin <aborodin@vmail.ru>, 2013-2022
This file is part of the Midnight Commander.
@ -145,10 +145,11 @@ clean_sort_keys (dir_list * list, int start, int count)
*/
static gboolean
handle_dirent (struct vfs_dirent *dp, const char *filter, struct stat *buf1, gboolean * link_to_dir,
gboolean * stale_link)
handle_dirent (struct vfs_dirent *dp, const file_filter_t * filter, struct stat *buf1,
gboolean * link_to_dir, gboolean * stale_link)
{
vfs_path_t *vpath;
gboolean ok = TRUE;
if (DIR_IS_DOT (dp->d_name) || DIR_IS_DOTDOT (dp->d_name))
return FALSE;
@ -176,8 +177,15 @@ handle_dirent (struct vfs_dirent *dp, const char *filter, struct stat *buf1, gbo
vfs_path_free (vpath, TRUE);
return (S_ISDIR (buf1->st_mode) || *link_to_dir || filter == NULL
|| mc_search (filter, NULL, dp->d_name, MC_SEARCH_T_GLOB));
if (filter != NULL && filter->handler != NULL)
{
gboolean files_only = (filter->flags & SELECT_FILES_ONLY) != 0;
ok = ((S_ISDIR (buf1->st_mode) || *link_to_dir) && files_only)
|| mc_search_run (filter->handler, dp->d_name, 0, strlen (dp->d_name), NULL);
}
return ok;
}
/* --------------------------------------------------------------------------------------------- */
@ -620,7 +628,7 @@ handle_path (const char *path, struct stat * buf1, gboolean * link_to_dir, gbool
gboolean
dir_list_load (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
const dir_sort_options_t * sort_op, const char *filter)
const dir_sort_options_t * sort_op, const file_filter_t * filter)
{
DIR *dirp;
struct vfs_dirent *dp;
@ -693,7 +701,7 @@ if_link_is_exe (const vfs_path_t * full_name_vpath, const file_entry_t * file)
gboolean
dir_list_reload (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
const dir_sort_options_t * sort_op, const char *filter)
const dir_sort_options_t * sort_op, const file_filter_t * filter)
{
DIR *dirp;
struct vfs_dirent *dp;
@ -814,3 +822,14 @@ dir_list_reload (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
}
/* --------------------------------------------------------------------------------------------- */
void
file_filter_clear (file_filter_t * filter)
{
MC_PTR_FREE (filter->value);
mc_search_free (filter->handler);
filter->handler = NULL;
/* keep filter->flags */
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -8,6 +8,7 @@
#include <sys/stat.h>
#include "lib/global.h"
#include "lib/search.h"
#include "lib/util.h"
#include "lib/vfs/vfs.h"
@ -23,6 +24,16 @@ typedef enum
DIR_CLOSE
} dir_list_cb_state_t;
/* selection flags */
typedef enum
{
SELECT_FILES_ONLY = 1 << 0,
SELECT_MATCH_CASE = 1 << 1,
SELECT_SHELL_PATTERNS = 1 << 2
} select_flags_t;
#define FILE_FILTER_DEFAULT_FLAGS (SELECT_FILES_ONLY | SELECT_MATCH_CASE | SELECT_SHELL_PATTERNS)
/* dir_list callback */
typedef void (*dir_list_cb_fn) (dir_list_cb_state_t state, void *data);
@ -51,6 +62,14 @@ typedef struct dir_sort_options_struct
gboolean exec_first; /**< executables are at top of list */
} dir_sort_options_t;
/* filter */
typedef struct
{
char *value;
mc_search_t *handler;
select_flags_t flags;
} file_filter_t;
/*** global variables defined in .c file *********************************************************/
/*** declarations of public functions ************************************************************/
@ -60,9 +79,9 @@ gboolean dir_list_append (dir_list * list, const char *fname, const struct stat
gboolean link_to_dir, gboolean stale_link);
gboolean dir_list_load (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
const dir_sort_options_t * sort_op, const char *filter);
const dir_sort_options_t * sort_op, const file_filter_t * filter);
gboolean dir_list_reload (dir_list * list, const vfs_path_t * vpath, GCompareFunc sort,
const dir_sort_options_t * sort_op, const char *filter);
const dir_sort_options_t * sort_op, const file_filter_t * filter);
void dir_list_sort (dir_list * list, GCompareFunc sort, const dir_sort_options_t * sort_op);
gboolean dir_list_init (dir_list * list);
void dir_list_clean (dir_list * list);
@ -83,6 +102,8 @@ int sort_inode (file_entry_t * a, file_entry_t * b);
gboolean if_link_is_exe (const vfs_path_t * full_name, const file_entry_t * file);
void file_filter_clear (file_filter_t * filter);
/*** inline functions ****************************************************************************/
static inline gboolean

View File

@ -991,7 +991,7 @@ display_mini_info (WPanel * panel)
{
Widget *w = WIDGET (panel);
if (!panels_options.show_mini_info)
if (!panels_options.show_mini_info || panel->selected < 0)
return;
widget_gotoyx (w, panel_lines (panel) + 3, 1);
@ -1497,6 +1497,8 @@ panel_destroy (WPanel * p)
}
g_free (p->dir_history.name);
file_filter_clear (&p->filter);
g_slist_free_full (p->format, (GDestroyNotify) format_item_free);
g_slist_free_full (p->status_format, (GDestroyNotify) format_item_free);
@ -1592,10 +1594,10 @@ panel_print_header (const WPanel * panel)
g_string_append (format_txt, fi->title);
if (panel->filter != NULL && strcmp (fi->id, "name") == 0)
if (panel->filter.handler != NULL && strcmp (fi->id, "name") == 0)
{
g_string_append (format_txt, " [");
g_string_append (format_txt, panel->filter);
g_string_append (format_txt, panel->filter.value);
g_string_append (format_txt, "]");
}
@ -2529,7 +2531,7 @@ mark_file_left (WPanel * panel)
static mc_search_t *
panel_select_unselect_files_dialog (select_flags_t * flags, const char *title,
const char *history_name, const char *help_section)
const char *history_name, const char *help_section, char **str)
{
gboolean files_only = (*flags & SELECT_FILES_ONLY) != 0;
gboolean case_sens = (*flags & SELECT_MATCH_CASE) != 0;
@ -2563,6 +2565,8 @@ panel_select_unselect_files_dialog (select_flags_t * flags, const char *title,
if (reg_exp == NULL || *reg_exp == '\0')
{
g_free (reg_exp);
if (str != NULL)
*str = NULL;
return SELECT_RESET;
}
@ -2571,7 +2575,10 @@ panel_select_unselect_files_dialog (select_flags_t * flags, const char *title,
search->is_entire_line = TRUE;
search->is_case_sensitive = case_sens;
g_free (reg_exp);
if (str != NULL)
*str = reg_exp;
else
g_free (reg_exp);
if (!mc_search_prepare (search))
{
@ -2603,7 +2610,7 @@ panel_select_unselect_files (WPanel * panel, const char *title, const char *hist
int i;
search = panel_select_unselect_files_dialog (&panels_options.select_flags, title, history_name,
help_section);
help_section, NULL);
if (search == NULL || search == SELECT_RESET || search == SELECT_ERROR)
return;
@ -2663,17 +2670,19 @@ panel_select_invert_files (WPanel * panel)
static void
panel_do_set_filter (WPanel * panel)
{
char *reg_exp;
const char *x;
file_filter_t ff = {.value = NULL,.handler = NULL,.flags = panel->filter.flags };
x = panel->filter != NULL ? panel->filter : easy_patterns ? "*" : ".";
ff.handler =
panel_select_unselect_files_dialog (&ff.flags, _("Filter"), MC_HISTORY_FM_PANEL_FILTER,
"[Filter...]", &ff.value);
reg_exp = input_dialog_help (_("Filter"),
_("Set expression for filtering filenames"),
"[Filter...]", MC_HISTORY_FM_PANEL_FILTER, x, FALSE,
INPUT_COMPLETE_FILENAMES);
if (reg_exp != NULL)
panel_set_filter (panel, reg_exp);
if (ff.handler == NULL || ff.handler == SELECT_ERROR)
return;
if (ff.handler == SELECT_RESET)
ff.handler = NULL;
panel_set_filter (panel, &ff);
}
/* --------------------------------------------------------------------------------------------- */
@ -3339,7 +3348,7 @@ panel_do_cd_int (WPanel * panel, const vfs_path_t * new_dir_vpath, enum cd_enum
panel_clean_dir (panel);
if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
&panel->sort_info, panel->filter))
&panel->sort_info, &panel->filter))
message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
try_to_select (panel, get_parent_dir_name (panel->cwd_vpath, olddir_vpath));
@ -4383,6 +4392,8 @@ panel_sized_empty_new (const char *panel_name, int y, int x, int lines, int cols
panel->list_format = list_full;
panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
panel->filter.flags = FILE_FILTER_DEFAULT_FLAGS;
for (i = 0; i < LIST_FORMATS; i++)
panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
@ -4473,7 +4484,7 @@ panel_sized_with_dir_new (const char *panel_name, int y, int x, int lines, int c
/* Load the default format */
if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
&panel->sort_info, panel->filter))
&panel->sort_info, &panel->filter))
message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
/* Restore old right path */
@ -4521,7 +4532,7 @@ panel_reload (WPanel * panel)
show_dir (panel);
if (!dir_list_reload (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
&panel->sort_info, panel->filter))
&panel->sort_info, &panel->filter))
message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
panel->dirty = TRUE;
@ -4594,15 +4605,15 @@ set_panel_formats (WPanel * p)
/* --------------------------------------------------------------------------------------------- */
void
panel_set_filter (WPanel * panel, char *filter)
panel_set_filter (WPanel * panel, const file_filter_t * filter)
{
MC_PTR_FREE (panel->filter);
MC_PTR_FREE (panel->filter.value);
mc_search_free (panel->filter.handler);
panel->filter.handler = NULL;
/* Three ways to clear filter: NULL, "", "*" */
if (filter == NULL || filter[0] == '\0' || (filter[0] == '*' && filter[1] == '\0'))
g_free (filter);
else
panel->filter = filter;
/* NULL to clear filter */
if (filter != NULL)
panel->filter = *filter;
reread_cmd ();
}

View File

@ -49,16 +49,7 @@ typedef enum
UP_ONLY_CURRENT = 2
} panel_update_flags_t;
/* selection flags */
typedef enum
{
SELECT_FILES_ONLY = 1 << 0,
SELECT_MATCH_CASE = 1 << 1,
SELECT_SHELL_PATTERNS = 1 << 2
} select_flags_t;
/* run mode and params */
enum cd_enum
{
cd_parse_command,
@ -129,7 +120,7 @@ typedef struct
gboolean user_mini_status; /* Is user_status_format used */
char *user_status_format[LIST_FORMATS]; /* User format for status line */
char *filter; /* File name filter */
file_filter_t filter; /* File name filter */
struct
{
@ -179,7 +170,7 @@ vfs_path_t *remove_encoding_from_path (const vfs_path_t * vpath);
void update_panels (panel_update_flags_t flags, const char *current_file);
int set_panel_formats (WPanel * p);
void panel_set_filter (WPanel * panel, char *filter);
void panel_set_filter (WPanel * panel, const file_filter_t * filter);
void try_to_select (WPanel * panel, const char *name);