Branch: refs/heads/master Author: xiota github@mentalfossa.com Committer: xiota github@mentalfossa.com Date: Tue, 07 Mar 2023 05:03:25 UTC Commit: 7e86828684c07622f2c2387db1785c73a2b04c50 https://github.com/geany/geany-plugins/commit/7e86828684c07622f2c2387db1785c...
Log Message: ----------- Project Organizer: Add ability to open file manager and terminal
File manager/terminal are opened at the location of the selected file in the tree view. If nothing is selected, the location of the current document is used. If the current document does not have a path, the project directory is used. If the project directory cannot be located, the current directory is used.
The file manager is opened with the path as the first argument.
The terminal path is set using the PWD.
Modified Paths: -------------- projectorganizer/src/prjorg-menu.c projectorganizer/src/prjorg-project.h projectorganizer/src/prjorg-sidebar.c projectorganizer/src/prjorg-sidebar.h
Modified: projectorganizer/src/prjorg-menu.c 8 lines changed, 8 insertions(+), 0 deletions(-) =================================================================== @@ -43,6 +43,8 @@ enum KB_FIND_FILE, KB_FIND_TAG, KB_FOCUS_SIDEBAR, + KB_OPEN_FILE_MANAGER, + KB_OPEN_TERMINAL, KB_COUNT };
@@ -408,6 +410,12 @@ void prjorg_menu_init(void) keybindings_set_item(key_group, KB_FOCUS_SIDEBAR, (GeanyKeyCallback)prjorg_sidebar_focus_project_tab, 0, 0, "focus_project_sidebar", _("Focus Project Sidebar"), NULL);
+ keybindings_set_item(key_group, KB_OPEN_FILE_MANAGER, (GeanyKeyCallback)on_open_file_manager, + 0, 0, "open_file_manager", _("Open File Manager at file location"), NULL); + + keybindings_set_item(key_group, KB_OPEN_TERMINAL, (GeanyKeyCallback)on_open_terminal, + 0, 0, "open_terminal", _("Open Terminal at file location"), NULL); + s_context_sep_item = gtk_separator_menu_item_new(); gtk_widget_show(s_context_sep_item); gtk_menu_shell_prepend(GTK_MENU_SHELL(geany->main_widgets->editor_menu), s_context_sep_item);
Modified: projectorganizer/src/prjorg-project.h 16 lines changed, 16 insertions(+), 0 deletions(-) =================================================================== @@ -64,6 +64,22 @@ void prjorg_project_remove_single_tm_file(gchar *utf8_filename);
gboolean prjorg_project_is_in_project(const gchar *utf8_filename);
+ +/* set open command based on OS */ +#if defined(_WIN32) || defined(G_OS_WIN32) +#define PRJORG_COMMAND_OPEN "start" +#define PRJORG_COMMAND_TERMINAL "PowerShell" +#define PRJORG_COMMAND_TERMINAL_ALT "" +#elif defined(__APPLE__) +#define PRJORG_COMMAND_OPEN "open" +#define PRJORG_COMMAND_TERMINAL "open -b com.apple.terminal" +#define PRJORG_COMMAND_TERMINAL_ALT "" +#else +#define PRJORG_COMMAND_OPEN "xdg-open" +#define PRJORG_COMMAND_TERMINAL "xterm" +#define PRJORG_COMMAND_TERMINAL_ALT "/usr/bin/x-terminal-emulator" +#endif + /* In the code we create a list of all files but we want to keep empty directories * in the list for which we create a fake file name with the PROJORG_DIR_ENTRY * value. */
Modified: projectorganizer/src/prjorg-sidebar.c 172 lines changed, 143 insertions(+), 29 deletions(-) =================================================================== @@ -300,6 +300,129 @@ static void on_follow_active(GtkToggleToolButton *button, G_GNUC_UNUSED gpointer }
+// returns path to selection if dir +// otherwise returns parent +// returned string must be freed +static gchar* get_dir_of_selection() +{ + GtkTreeSelection *treesel; + GtkTreeModel *model; + GtkTreeIter iter, parent; + gchar *path = NULL; + + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s_file_view)); + if (gtk_tree_selection_get_selected(treesel, &model, &iter)) + { + path = build_path(&iter); + if (!g_file_test(path, G_FILE_TEST_IS_DIR)) + { + g_free(path); + path = NULL; + if (gtk_tree_model_iter_parent(model, &parent, &iter)) + path = build_path(&parent); + } + } + return path; +} + + +/* if get_dir_of_selection() fails, + * returns parent of current document, project folder, or home folder */ +static gchar *get_fallback_dir_of_selection(void) +{ + gchar *locale_path; + + /* get path from treeview selection */ + locale_path = get_dir_of_selection(); + + /* get path from current document */ + if (!locale_path) + { + GeanyDocument *doc; + + doc = document_get_current(); + if (DOC_VALID(doc) && doc->real_path) + { + locale_path = g_path_get_dirname(doc->real_path); + + if (locale_path && locale_path == '.') + { + g_free(locale_path); + locale_path = NULL; + } + } + } + + /* get path from project */ + if (!locale_path && geany_data->app->project) + { + gchar *utf8_path = NULL; + utf8_path = get_project_base_path(); + locale_path = utils_get_locale_from_utf8(utf8_path); + g_free(utf8_path); + } + + /* get current directory */ + if (!locale_path || !g_file_test(locale_path, G_FILE_TEST_IS_DIR)) + locale_path = g_strdup(g_get_current_dir()); + + /* get user home directory */ + if (!locale_path || !g_file_test(locale_path, G_FILE_TEST_IS_DIR)) + locale_path = g_strdup(g_get_home_dir()); + + return locale_path; +} + + +void on_open_file_manager(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data) +{ + gchar *locale_path; + locale_path = get_fallback_dir_of_selection(); + + if (locale_path) + { + gchar *command, *open_command; + + open_command = PRJORG_COMMAND_OPEN; + command = g_strconcat (open_command, " "", locale_path, """, NULL); + if (!spawn_async(locale_path, command, NULL, NULL, NULL, NULL)) + msgwin_status_add(_("Unable to open folder. Command unavailable: %s"), open_command); + + g_free(command); + g_free(locale_path); + } + else + { + msgwin_status_add(_("Unable to find folder.")); + } +} + + +void on_open_terminal(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data) +{ + gchar *locale_path, *open_command; + + if (g_file_test(PRJORG_COMMAND_TERMINAL_ALT, G_FILE_TEST_EXISTS)) + { + gchar *alt_command; + alt_command = utils_get_real_path(PRJORG_COMMAND_TERMINAL_ALT); + open_command = g_path_get_basename(alt_command); + g_free(alt_command); + } + else + { + open_command = g_strdup(PRJORG_COMMAND_TERMINAL); + } + + locale_path = get_fallback_dir_of_selection(); + if (!spawn_async(locale_path, open_command, NULL, NULL, NULL, NULL)) + msgwin_status_add(_("Unable to open terminal: %s"), open_command); + + g_free(locale_path); + g_free(open_command); +} + + static void on_add_external(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data) { gchar *utf8_base_path = get_project_base_path(); @@ -355,35 +478,11 @@ static void on_remove_external_dir(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_U }
-// returned string must be freed -static gchar* parent_dir_for_create() -{ - GtkTreeSelection *treesel; - GtkTreeModel *model; - GtkTreeIter iter, parent; - gchar *path = NULL; - - treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s_file_view)); - if (gtk_tree_selection_get_selected(treesel, &model, &iter)) - { - path = build_path(&iter); - if (!g_file_test(path, G_FILE_TEST_IS_DIR)) - { - g_free(path); - path = NULL; - if (gtk_tree_model_iter_parent(model, &parent, &iter)) - path = build_path(&parent); - } - } - return path; -} - - static void on_create_file(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data) { gchar *dir, *name;
- dir = parent_dir_for_create(); + dir = get_dir_of_selection(); if (dir == NULL) return;
@@ -414,7 +513,7 @@ static void on_create_dir(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpo { gchar *dir, *name;
- dir = parent_dir_for_create(); + dir = get_dir_of_selection(); if (dir == NULL) return;
@@ -1543,9 +1642,6 @@ void prjorg_sidebar_init(void) g_signal_connect(item, "clicked", G_CALLBACK(on_reload_project), NULL); gtk_container_add(GTK_CONTAINER(s_toolbar), item);
- item = GTK_WIDGET(gtk_separator_tool_item_new()); - gtk_container_add(GTK_CONTAINER(s_toolbar), item); - image = gtk_image_new_from_icon_name("folder-new", GTK_ICON_SIZE_SMALL_TOOLBAR); item = GTK_WIDGET(gtk_tool_button_new(image, NULL)); gtk_widget_set_tooltip_text(item, _("Add external directory")); @@ -1634,6 +1730,10 @@ void prjorg_sidebar_init(void) g_signal_connect((gpointer) item, "activate", G_CALLBACK(expand_all), NULL); s_popup_menu.expand = item;
+ item = gtk_separator_menu_item_new(); + gtk_widget_show(item); + gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); + item = menu_item_new("edit-find", _("Find in Files...")); gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_find_in_files), NULL); @@ -1653,6 +1753,20 @@ void prjorg_sidebar_init(void) gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+ item = menu_item_new("folder-open", _("Open File Manager")); + gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); + g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_open_file_manager), NULL); + s_popup_menu.find_in_directory = item; + + item = menu_item_new("terminal", _("Open Terminal")); + gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); + g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_open_terminal), NULL); + s_popup_menu.find_in_directory = item; + + item = gtk_separator_menu_item_new(); + gtk_widget_show(item); + gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); + item = menu_item_new("list-remove", _("Remove External Directory")); gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_remove_external_dir), NULL);
Modified: projectorganizer/src/prjorg-sidebar.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -31,5 +31,7 @@ void prjorg_sidebar_update(gboolean reload);
void prjorg_sidebar_focus_project_tab(void);
+void on_open_file_manager(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data); +void on_open_terminal(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data);
#endif
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).