static void gb_editor_view_actions_save (GSimpleAction *action, GVariant *param, gpointer user_data) { GbEditorView *self = user_data; IdeContext *context; IdeBufferManager *buffer_manager; IdeFile *file; IdeProgress *progress = NULL; IdeVcs *vcs; GFile *workdir; g_assert (GB_IS_EDITOR_VIEW (self)); file = ide_buffer_get_file (IDE_BUFFER (self->document)); context = ide_buffer_get_context (IDE_BUFFER (self->document)); buffer_manager = ide_context_get_buffer_manager (context); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); if (ide_file_get_is_temporary (file)) { GtkDialog *dialog; GtkWidget *toplevel; GtkWidget *suggested; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG, "action", GTK_FILE_CHOOSER_ACTION_SAVE, "do-overwrite-confirmation", TRUE, "local-only", FALSE, "modal", TRUE, "select-multiple", FALSE, "show-hidden", FALSE, "transient-for", toplevel, "title", _("Save Document"), NULL); gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), workdir, NULL); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Cancel"), GTK_RESPONSE_CANCEL, _("Save"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); suggested = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_style_context_add_class (gtk_widget_get_style_context (suggested), GTK_STYLE_CLASS_SUGGESTED_ACTION); g_signal_connect (dialog, "response", G_CALLBACK (save_temp_response), g_object_ref (self)); gtk_window_present (GTK_WINDOW (dialog)); return; } ide_buffer_manager_save_file_async (buffer_manager, IDE_BUFFER (self->document), file, &progress, NULL, save_file_cb, g_object_ref (self)); g_object_bind_property (progress, "fraction", self->progress_bar, "fraction", G_BINDING_SYNC_CREATE); gtk_widget_show (GTK_WIDGET (self->progress_bar)); g_clear_object (&progress); }
static void gb_vim_complete_edit_files (GtkSourceView *source_view, const gchar *command, GPtrArray *ar, const gchar *prefix) { GbWorkbench *workbench; IdeContext *context; IdeVcs *vcs; GFile *workdir; g_autoptr(GFile) child = NULL; g_autoptr(GFile) parent = NULL; IDE_ENTRY; g_assert (command); g_assert (ar); g_assert (prefix); if (!(workbench = gb_widget_get_workbench (GTK_WIDGET (source_view))) || !(context = gb_workbench_get_context (workbench)) || !(vcs = ide_context_get_vcs (context)) || !(workdir = ide_vcs_get_working_directory (vcs))) IDE_EXIT; child = g_file_get_child (workdir, prefix); if (g_file_query_exists (child, NULL)) { if (g_file_query_file_type (child, 0, NULL) == G_FILE_TYPE_DIRECTORY) { g_autoptr(GFileEnumerator) fe = NULL; GFileInfo *descendent; if (!g_str_has_suffix (prefix, "/")) { g_ptr_array_add (ar, g_strdup_printf ("%s %s/", command, prefix)); IDE_EXIT; } fe = g_file_enumerate_children (child, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); g_ptr_array_add (ar, g_strdup_printf ("%s %s%s", command, prefix, name)); g_object_unref (descendent); } IDE_EXIT; } } parent = g_file_get_parent (child); if (parent != NULL) { g_autoptr(GFileEnumerator) fe = NULL; g_autofree gchar *relpath = NULL; GFileInfo *descendent; const gchar *slash; relpath = g_file_get_relative_path (workdir, parent); if (relpath && g_str_has_prefix (relpath, "./")) { gchar *tmp = relpath; relpath = g_strdup (relpath + 2); g_free (tmp); } #ifdef IDE_ENABLE_TRACE { g_autofree gchar *parent_path = g_file_get_path (parent); IDE_TRACE_MSG ("parent_path: %s", parent_path); } #endif if ((slash = strrchr (prefix, G_DIR_SEPARATOR))) prefix = slash + 1; fe = g_file_enumerate_children (parent, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); IDE_TRACE_MSG ("name=%s prefix=%s", name, prefix); if (name && g_str_has_prefix (name, prefix)) { gchar *path; if (relpath) path = g_strdup_printf ("%s %s/%s", command, relpath, name); else path = g_strdup_printf ("%s %s", command, name); IDE_TRACE_MSG ("edit completion: %s", path); g_ptr_array_add (ar, path); } g_object_unref (descendent); } IDE_EXIT; } IDE_EXIT; }
static void gb_terminal_respawn (GbTerminalView *self, VteTerminal *terminal) { g_autoptr(GPtrArray) args = NULL; g_autoptr(IdeSubprocess) subprocess = NULL; g_autoptr(IdeSubprocessLauncher) launcher = NULL; g_autofree gchar *workpath = NULL; g_autofree gchar *shell = NULL; GtkWidget *toplevel; GError *error = NULL; IdeContext *context; IdeVcs *vcs; VtePty *pty = NULL; GFile *workdir; gint64 now; int tty_fd = -1; gint stdout_fd = -1; gint stderr_fd = -1; IDE_ENTRY; g_assert (GB_IS_TERMINAL_VIEW (self)); vte_terminal_reset (terminal, TRUE, TRUE); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); if (!IDE_IS_WORKBENCH (toplevel)) IDE_EXIT; /* Prevent flapping */ now = g_get_monotonic_time (); if ((now - self->last_respawn) < (G_USEC_PER_SEC / 10)) IDE_EXIT; self->last_respawn = now; context = ide_workbench_get_context (IDE_WORKBENCH (toplevel)); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); workpath = g_file_get_path (workdir); shell = gb_terminal_view_discover_shell (NULL, &error); if (shell == NULL) { g_warning ("Failed to discover user shell: %s", error->message); /* We prefer bash in flatpak over sh */ if (ide_is_flatpak ()) shell = g_strdup ("/bin/bash"); else shell = vte_get_user_shell (); g_clear_error (&error); } args = g_ptr_array_new (); g_ptr_array_add (args, (gchar *)shell); g_ptr_array_add (args, NULL); pty = vte_terminal_pty_new_sync (terminal, VTE_PTY_DEFAULT | VTE_PTY_NO_LASTLOG | VTE_PTY_NO_UTMP | VTE_PTY_NO_WTMP, NULL, &error); if (pty == NULL) IDE_GOTO (failure); vte_terminal_set_pty (terminal, pty); if (-1 == (tty_fd = gb_vte_pty_create_slave (pty))) IDE_GOTO (failure); /* dup() is safe as it will inherit O_CLOEXEC */ if (-1 == (stdout_fd = dup (tty_fd)) || -1 == (stderr_fd = dup (tty_fd))) IDE_GOTO (failure); /* XXX: It would be nice to allow using the runtimes launcher */ launcher = ide_subprocess_launcher_new (0); ide_subprocess_launcher_set_run_on_host (launcher, TRUE); ide_subprocess_launcher_set_clear_env (launcher, FALSE); ide_subprocess_launcher_set_cwd (launcher, workpath); ide_subprocess_launcher_push_args (launcher, (const gchar * const *)args->pdata); ide_subprocess_launcher_take_stdin_fd (launcher, tty_fd); ide_subprocess_launcher_take_stdout_fd (launcher, stdout_fd); ide_subprocess_launcher_take_stderr_fd (launcher, stderr_fd); ide_subprocess_launcher_setenv (launcher, "TERM", "xterm-256color", TRUE); ide_subprocess_launcher_setenv (launcher, "INSIDE_GNOME_BUILDER", PACKAGE_VERSION, TRUE); ide_subprocess_launcher_setenv (launcher, "SHELL", shell, TRUE); tty_fd = -1; stdout_fd = -1; stderr_fd = -1; if (NULL == (subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error))) IDE_GOTO (failure); ide_subprocess_wait_async (subprocess, NULL, gb_terminal_view_wait_cb, g_object_ref (terminal)); failure: if (tty_fd != -1) close (tty_fd); if (stdout_fd != -1) close (stdout_fd); g_clear_object (&pty); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } IDE_EXIT; }