search: Add project-wide search and replace feature.

This commit is contained in:
Al Poole 2017-09-28 01:23:18 +01:00
parent 5cefe27e48
commit c826dee557
5 changed files with 296 additions and 2 deletions

View File

@ -17,3 +17,104 @@ edi_file_path_hidden(const char *path)
return EINA_FALSE;
}
void
edi_file_text_replace(const char *path, const char *search, const char *replace)
{
char *map, *tempfilepath, *found;
FILE *tempfile;
Eina_File *f;
unsigned long long len, idx;
unsigned int slen;
f = eina_file_open(path, EINA_FALSE);
if (!f) return;
map = eina_file_map_all(f, EINA_FILE_POPULATE);
if (!map)
{
eina_file_close(f);
return;
}
len = eina_file_size_get(f);
if (!len)
{
eina_file_close(f);
return;
}
tempfilepath = malloc(strlen(path)) + 5;
sprintf(tempfilepath, "/tmp/%s.tmp", ecore_file_file_get(path));
tempfile = fopen(tempfilepath, "wb");
if (!tempfile) goto done;
idx = 0;
found = strstr(&map[idx], search);
if (!found)
{
fclose(tempfile);
unlink(tempfilepath);
goto done;
}
slen = strlen(search);
while (idx < len)
{
if (!found || &map[idx] < found)
{
fprintf(tempfile, "%c", map[idx]);
idx++;
}
else
{
fprintf(tempfile, "%s", replace);
idx += slen;
found = strstr(&map[idx], search);
}
}
fclose(tempfile);
ecore_file_mv(tempfilepath, path);
done:
eina_file_map_free(f, map);
eina_file_close(f);
}
static void
_edi_file_text_replace_all(const char *directory, const char *search, const char *replace)
{
char *path, *file;
Eina_List *files;
files = ecore_file_ls(directory);
EINA_LIST_FREE(files, file)
{
path = edi_path_append(directory, file);
if (!edi_file_path_hidden(path))
{
if (ecore_file_is_dir(path))
{
_edi_file_text_replace_all(path, search, replace);
}
else
{
edi_file_text_replace(path, search, replace);
}
}
free(path);
free(file);
}
if (files)
eina_list_free(files);
}
void
edi_file_text_replace_all(const char *search, const char *replace)
{
_edi_file_text_replace_all(edi_project_get(), search, replace);
}

View File

@ -31,6 +31,27 @@ extern "C" {
Eina_Bool edi_file_path_hidden(const char *path);
/**
* Replace all occurences of text within whole project.
*
* @param search The text to be replaced.
* @param replace The text that will replace.
*
* @ingroup Lookup
*/
void edi_file_text_replace_all(const char *search, const char *replace);
/**
* Replace all occurences of text within given file.
*
* @param path The path of the file to replace all occurences of the text.
* @param search The text to be replaced.
* @param replace The text that will replace.
*
* @ingroup Lookup
*/
void edi_file_text_replace(const char *path, const char *search, const char *replace);
/**
* @}
*/

View File

@ -926,6 +926,13 @@ _edi_menu_find_project_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
edi_mainview_project_search_popup_show();
}
static void
_edi_menu_find_replace_project_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
edi_mainview_project_replace_popup_show();
}
static void
_edi_menu_findfile_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
@ -1137,6 +1144,7 @@ _edi_menu_setup(Evas_Object *win)
elm_menu_item_add(menu, menu_it, "go-jump", _("Goto Line ..."), _edi_menu_goto_cb, NULL);
elm_menu_item_separator_add(menu, menu_it);
elm_menu_item_add(menu, menu_it, "edit-find", _("Find in project ..."), _edi_menu_find_project_cb, NULL);
elm_menu_item_add(menu, menu_it, "edit-find-replace", _("Replace in project ..."), _edi_menu_find_replace_project_cb, NULL);
menu_it = elm_menu_item_add(menu, NULL, NULL, _("View"), NULL, NULL);
elm_menu_item_add(menu, menu_it, "window-new", _("New Window"), _edi_menu_view_open_window_cb, NULL);

View File

@ -14,7 +14,8 @@
#include "editor/edi_editor.h"
#include "edi_content_provider.h"
#include "../edi_searchpanel.h"
#include "edi_searchpanel.h"
#include "edi_file.h"
#include "edi_private.h"
#include "edi_config.h"
@ -465,6 +466,35 @@ edi_mainview_goto_popup_show()
edi_mainview_panel_goto_popup_show(_current_panel);
}
static void
_edi_mainview_popup_message_close_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Evas_Object *popup = data;
evas_object_del(popup);
}
static void
_edi_mainview_popup_message_open(const char *message)
{
Evas_Object *popup, *button;
popup = elm_popup_add(_main_win);
elm_object_part_text_set(popup, "title,text",
message);
button = elm_button_add(popup);
elm_object_text_set(button, _("OK"));
elm_object_part_content_set(popup, "button1", button);
evas_object_smart_callback_add(button, "clicked",
_edi_mainview_popup_message_close_cb, popup);
evas_object_show(popup);
}
static void
_edi_mainview_project_search_popup_cancel_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
@ -482,7 +512,11 @@ _edi_mainview_project_search_cb(void *data,
char *text;
text_markup = elm_object_text_get((Evas_Object *) data);
if (!text_markup || !text_markup[0]) return;
if (!text_markup || !text_markup[0])
{
_edi_mainview_popup_message_open(_("Please enter a valid search term."));
return;
}
text = elm_entry_markup_to_utf8(text_markup);
@ -517,6 +551,7 @@ edi_mainview_project_search_popup_show(void)
_("Search for (whole project)"));
box = elm_box_add(popup);
evas_object_show(box);
sep = elm_separator_add(box);
elm_separator_horizontal_set(sep, EINA_TRUE);
evas_object_show(sep);
@ -565,6 +600,127 @@ edi_mainview_project_search_popup_show(void)
evas_object_show(popup);
elm_object_focus_set(input, EINA_TRUE);
}
static void
_edi_mainview_project_replace_cb(void *data,
Evas_Object *obj,
void *event_info EINA_UNUSED)
{
const char *search_markup, *replace_markup;
char *search, *replace;
search_markup = elm_object_text_get(evas_object_data_get(obj, "search"));
if (!search_markup || !search_markup[0])
{
_edi_mainview_popup_message_open(_("Please enter a valid search string."));
return;
}
replace_markup = elm_object_text_get(data);
if (!replace_markup || !replace_markup[0])
{
_edi_mainview_popup_message_open(_("Please enter a valid replace string."));
return;
}
if (!strcmp(replace_markup, search_markup))
{
_edi_mainview_popup_message_open(_("Strings cannot match."));
return;
}
search = elm_entry_markup_to_utf8(search_markup);
replace = elm_entry_markup_to_utf8(replace_markup);
edi_file_text_replace_all(search, replace);
free(search);
free(replace);
evas_object_del(_edi_mainview_search_project_popup);
}
void
edi_mainview_project_replace_popup_show(void)
{
Evas_Object *popup, *table, *box, *label, *sep, *search, *replace, *button;
popup = elm_popup_add(_main_win);
_edi_mainview_search_project_popup = popup;
elm_object_part_text_set(popup, "title,text", _("Search &amp; Replace"));
box = elm_box_add(popup);
elm_object_content_set(popup, box);
sep = elm_separator_add(box);
elm_separator_horizontal_set(sep, EINA_TRUE);
evas_object_show(sep);
elm_box_pack_end(box, sep);
label = elm_label_add(box);
elm_object_text_set(label, _("Replace all occurences of text within the whole project."));
evas_object_show(label);
elm_box_pack_end(box, label);
sep = elm_separator_add(box);
elm_separator_horizontal_set(sep, EINA_TRUE);
evas_object_show(sep);
elm_box_pack_end(box, sep);
table = elm_table_add(box);
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(table);
label = elm_label_add(table);
elm_object_text_set(label, _("Search: "));
evas_object_show(label);
elm_table_pack(table, label, 0, 0, 1, 1);
search = elm_entry_add(table);
elm_entry_single_line_set(search, EINA_TRUE);
elm_entry_scrollable_set(search, EINA_TRUE);
evas_object_size_hint_weight_set(search, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(search, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(search);
elm_table_pack(table, search, 1, 0, 1, 1);
label = elm_label_add(table);
elm_object_text_set(label, _("Replace: "));
evas_object_show(label);
elm_table_pack(table, label, 0, 1, 1, 1);
replace = elm_entry_add(table);
elm_entry_single_line_set(replace, EINA_TRUE);
elm_entry_scrollable_set(replace, EINA_TRUE);
evas_object_size_hint_weight_set(replace, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(replace, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(replace);
elm_table_pack(table, replace, 1, 1, 1, 1);
elm_box_pack_end(box, table);
sep = elm_separator_add(box);
elm_separator_horizontal_set(sep, EINA_TRUE);
evas_object_show(sep);
elm_box_pack_end(box, sep);
button = elm_button_add(popup);
elm_object_text_set(button, _("Cancel"));
elm_object_part_content_set(popup, "button1", button);
evas_object_smart_callback_add(button, "clicked",
_edi_mainview_project_search_popup_cancel_cb, NULL);
button = elm_button_add(popup);
evas_object_data_set(button, "search", search);
elm_object_text_set(button, _("Replace"));
elm_object_part_content_set(popup, "button2", button);
evas_object_smart_callback_add(button, "clicked",
_edi_mainview_project_replace_cb, replace);
evas_object_show(popup);
}
void
edi_mainview_panel_remove(Edi_Mainview_Panel *panel)
{

View File

@ -237,6 +237,14 @@ void edi_mainview_goto_popup_show();
*/
void edi_mainview_project_search_popup_show();
/**
* Present a popup to initiate a project-wide search and replace.
*
* @ingroup Content
*/
void edi_mainview_project_replace_popup_show();
/**
* @}
*