mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-23 04:46:55 +03:00
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:
parent
f20f5cc5cb
commit
a705b67288
@ -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 */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user