Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "syntax.h"

#ifndef APP_VERSION
#define APP_VERSION "0.16.3"
#define APP_VERSION "0.16.8"
#endif

/**
Expand All @@ -33,6 +33,8 @@ typedef struct _EditorWindow {
GHashTable *locked_paths; /**< Locked paths. */
GHashTable *git_file_status; /**< short Git marker. */
GtkWidget *status_label; /**< Status label. */
char *status_error_title; /**< Latest status error title. */
char *status_error_detail; /**< Latest status error detail. */
GtkWidget *syntax_combo; /**< Syntax combo. */
GtkWidget *indent_status_label; /**< Indent status label. */
GtkWidget *indent_dropdown; /**< Indent dropdown. */
Expand Down Expand Up @@ -81,6 +83,7 @@ typedef struct _EditorWindow {
char *topbar_fg_color; /**< Topbar fg color. */
char *bottombar_bg_color; /**< Bottombar bg color. */
char *bottombar_fg_color; /**< Bottombar fg color. */
char *status_error_color; /**< Status error color. */
char *button_bg_color; /**< Button bg color. */
char *button_fg_color; /**< Button fg color. */
char *button_hover_bg_color; /**< Button hover bg color. */
Expand Down Expand Up @@ -163,6 +166,20 @@ gboolean app_window_close_all_tabs(EditorWindow *win);
* @brief App window set status.
*/
void app_window_set_status(EditorWindow *win, const char *text);
/**
* @brief App window set error status.
*/
void app_window_set_error_status(EditorWindow *win,
const char *short_text,
const char *detail);
/**
* @brief App window clear error status.
*/
void app_window_clear_error_status(EditorWindow *win);
/**
* @brief App window show status error.
*/
void app_window_show_status_error(EditorWindow *win);
/**
* @brief App window is file locked.
*/
Expand Down
33 changes: 12 additions & 21 deletions src/app/app_file_search_actions.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,9 @@ void action_open_folder(GtkWidget *widget, gpointer user_data) {
* @brief Cleaf executable path.
*/
static char *cleaf_executable_path(void) {
GError *error = NULL;
g_autoptr(GError) error = NULL;
char *path = g_file_read_link("/proc/self/exe", &error);
if (path) return path;
g_clear_error(&error);

const char *prgname = g_get_prgname();
if (prgname && prgname[0] != '\0') return g_strdup(prgname);
Expand All @@ -97,37 +96,30 @@ void action_open_folder_new_instance(GtkWidget *widget, gpointer user_data) {
EditorWindow *win = user_data;
if (!win) return;

char *folder = cleaf_select_folder_dialog(app_window_gtk(win),
"Open Folder in New Instance");
g_autofree char *folder = cleaf_select_folder_dialog(app_window_gtk(win),
"Open Folder in New Instance");
if (!folder) return;

char *exe = cleaf_executable_path();
g_autofree char *exe = cleaf_executable_path();
if (!exe) {
dialog_error(app_window_gtk(win), "Could not launch instance",
"Cleaf could not determine its executable path.");
g_free(folder);
app_window_set_error_status(win, "Could not launch instance",
"Cleaf could not determine its executable path.");
return;
}

char *argv[] = { exe, folder, NULL };
GError *error = NULL;
g_autoptr(GError) error = NULL;
gboolean ok = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, &error);
if (!ok) {
dialog_error(app_window_gtk(win), "Could not launch instance",
error ? error->message : "Unknown launch error.");
g_clear_error(&error);
app_window_set_error_status(win, "Could not launch instance",
error ? error->message : "Unknown launch error.");
} else {
char *display = g_filename_display_basename(folder);
char *msg = g_strdup_printf("Opened new instance for: %s",
display ? display : folder);
g_autofree char *display = g_filename_display_basename(folder);
g_autofree char *msg = g_strdup_printf("Opened new instance for: %s",
display ? display : folder);
app_window_set_status(win, msg);
g_free(msg);
g_free(display);
}

g_free(exe);
g_free(folder);
}


Expand Down Expand Up @@ -260,4 +252,3 @@ void action_syntax_diagnostics(GtkWidget *widget, gpointer user_data) {
g_free(diag);
}


7 changes: 3 additions & 4 deletions src/app/app_preference_actions.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ void choose_color_for_slot(EditorWindow *win,

GdkRGBA parsed;
if (!gdk_rgba_parse(&parsed, value)) {
dialog_error(app_window_gtk(win), "Invalid colour",
"Use a valid GTK colour, such as #1E1E1E.");
app_window_set_error_status(win, "Invalid colour",
"Use a valid GTK colour, such as #1E1E1E.");
g_free(value);
return;
}
Expand Down Expand Up @@ -234,6 +234,7 @@ void action_reset_all_backgrounds(GtkWidget *widget, gpointer user_data) {
g_clear_pointer(&win->topbar_fg_color, g_free);
g_clear_pointer(&win->bottombar_bg_color, g_free);
g_clear_pointer(&win->bottombar_fg_color, g_free);
g_clear_pointer(&win->status_error_color, g_free);
g_clear_pointer(&win->button_bg_color, g_free);
g_clear_pointer(&win->button_fg_color, g_free);
g_clear_pointer(&win->button_hover_bg_color, g_free);
Expand Down Expand Up @@ -269,5 +270,3 @@ void action_reset_all_backgrounds(GtkWidget *widget, gpointer user_data) {
apply_preferences_to_all_tabs(win);
cleaf_config_save(win);
}


6 changes: 5 additions & 1 deletion src/app/app_window_lifecycle.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static void codex_status_changed(CodexClient *client,
} else if (state == CODEX_CLIENT_FAILED) {
char *message = g_strdup_printf("Codex unavailable: %s",
detail ? detail : "unknown error");
app_window_set_status(win, message);
app_window_set_error_status(win, "Codex unavailable", message);
g_free(message);
}
}
Expand Down Expand Up @@ -70,6 +70,7 @@ EditorWindow *app_window_new(GtkApplication *application) {
win->topbar_fg_color = g_strdup("#d4d4d4");
win->bottombar_bg_color = g_strdup("#181a1f");
win->bottombar_fg_color = g_strdup("#d4d4d4");
win->status_error_color = g_strdup("#ff6b6b");
win->button_bg_color = g_strdup("#181a1f");
win->button_fg_color = g_strdup("#d4d4d4");
win->button_hover_bg_color = g_strdup("#2a2e3d");
Expand Down Expand Up @@ -229,6 +230,8 @@ void app_window_free(EditorWindow *win) {
if (win->project_roots) g_ptr_array_free(win->project_roots, TRUE);
if (win->locked_paths) g_hash_table_destroy(win->locked_paths);
if (win->git_file_status) g_hash_table_destroy(win->git_file_status);
g_free(win->status_error_title);
g_free(win->status_error_detail);
g_free(win->editor_bg_color);
g_free(win->editor_fg_color);
g_free(win->editor_gutter_bg_color);
Expand All @@ -246,6 +249,7 @@ void app_window_free(EditorWindow *win) {
g_free(win->topbar_fg_color);
g_free(win->bottombar_bg_color);
g_free(win->bottombar_fg_color);
g_free(win->status_error_color);
g_free(win->button_bg_color);
g_free(win->button_fg_color);
g_free(win->button_hover_bg_color);
Expand Down
44 changes: 43 additions & 1 deletion src/app/app_window_state.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,52 @@ GtkWindow *app_window_gtk(EditorWindow *win) {
void app_window_set_status(EditorWindow *win, const char *text) {
if (!win || !win->status_label) return;

app_window_clear_error_status(win);
// Empty string keeps the status label valid without showing stale text.
gtk_label_set_text(GTK_LABEL(win->status_label), text ? text : "");
}

/**
* @brief App window clear error status.
*/
void app_window_clear_error_status(EditorWindow *win) {
if (!win) return;
g_clear_pointer(&win->status_error_title, g_free);
g_clear_pointer(&win->status_error_detail, g_free);
if (win->status_label) {
gtk_widget_remove_css_class(win->status_label, "cleaf-status-error");
gtk_widget_set_tooltip_text(win->status_label, NULL);
}
}

/**
* @brief App window set error status.
*/
void app_window_set_error_status(EditorWindow *win,
const char *short_text,
const char *detail) {
if (!win || !win->status_label) return;

g_clear_pointer(&win->status_error_title, g_free);
g_clear_pointer(&win->status_error_detail, g_free);
win->status_error_title = g_strdup(short_text && short_text[0] ? short_text : "Error");
win->status_error_detail = g_strdup(detail && detail[0] ? detail : win->status_error_title);

gtk_label_set_text(GTK_LABEL(win->status_label), win->status_error_title);
gtk_widget_add_css_class(win->status_label, "cleaf-status-error");
gtk_widget_set_tooltip_text(win->status_label, "Click to show error details");
}

/**
* @brief App window show status error.
*/
void app_window_show_status_error(EditorWindow *win) {
if (!win || !win->status_error_detail) return;
dialog_error(app_window_gtk(win),
win->status_error_title ? win->status_error_title : "Error",
win->status_error_detail);
}


/**
* @brief Canonical or dup.
Expand Down Expand Up @@ -213,4 +255,4 @@ void app_window_note_path_renamed(EditorWindow *win,

g_free(old_canonical);
g_free(new_canonical);
}
}
20 changes: 20 additions & 0 deletions src/app_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,21 @@ GtkWidget *build_tool_panel(EditorWindow *win) {
return win->tool_revealer;
}

/**
* @brief On status label clicked.
*/
static void on_status_label_clicked(GtkGestureClick *gesture,
int n_press,
double x,
double y,
gpointer user_data) {
(void)gesture;
(void)n_press;
(void)x;
(void)y;
app_window_show_status_error(user_data);
}

/**
* @brief Build bottom bar.
*/
Expand All @@ -495,6 +510,11 @@ GtkWidget *build_bottom_bar(EditorWindow *win) {
gtk_label_set_ellipsize(GTK_LABEL(win->status_label), PANGO_ELLIPSIZE_END);
gtk_widget_add_css_class(win->status_label, "cleaf-status");
gtk_widget_set_size_request(win->status_label, 180, -1);
GtkGesture *status_click = gtk_gesture_click_new();
g_signal_connect(status_click, "pressed",
G_CALLBACK(on_status_label_clicked), win);
gtk_widget_add_controller(win->status_label,
GTK_EVENT_CONTROLLER(status_click));
gtk_box_append(GTK_BOX(bottom), win->status_label);

gtk_box_append(GTK_BOX(bottom), tool_button_new("Find", "Open find panel (Ctrl+F)", G_CALLBACK(action_show_find), win));
Expand Down
1 change: 1 addition & 0 deletions src/app_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void app_window_apply_css(EditorWindow *win) {
win->tab_active_fg_color,
win->topbar_bg_color, win->topbar_fg_color,
win->bottombar_bg_color, win->bottombar_fg_color,
win->status_error_color,
win->button_bg_color, win->button_fg_color,
win->button_hover_bg_color,
win->button_active_bg_color,
Expand Down
19 changes: 6 additions & 13 deletions src/codex_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static gboolean codex_client_write(CodexClient *client, char *message) {
g_free(message);
return FALSE; /**< False. */
}
GError *error = NULL;
g_autoptr(GError) error = NULL;
gboolean written = g_output_stream_write_all(client->input,
message,
strlen(message),
Expand All @@ -110,7 +110,6 @@ static gboolean codex_client_write(CodexClient *client, char *message) {
if (!written) {
codex_client_set_state(client, CODEX_CLIENT_FAILED,
error ? error->message : "write failed");
g_clear_error(&error);
}
return written; /**< Written. */
}
Expand Down Expand Up @@ -511,16 +510,15 @@ static void codex_client_line_ready(GObject *source,
GAsyncResult *result,
gpointer user_data) {
CodexClient *client = user_data;
GError *error = NULL;
g_autoptr(GError) error = NULL;
gsize length = 0u;
char *line = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(source),
result, &length, &error);
g_autofree char *line = g_data_input_stream_read_line_finish(G_DATA_INPUT_STREAM(source),
result, &length, &error);
if (!line) {
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
codex_client_set_state(client, CODEX_CLIENT_FAILED,
error ? error->message : "Codex exited");
}
g_clear_error(&error);
codex_client_unref(client);
return;
}
Expand All @@ -529,10 +527,7 @@ static void codex_client_line_ready(GObject *source,
if (codex_protocol_parse(line, &root, &error)) {
codex_client_handle_message(client, root);
json_node_free(root);
} else {
g_clear_error(&error);
}
g_free(line);
if (!client->disposing) codex_client_read_next(client);
codex_client_unref(client);
}
Expand Down Expand Up @@ -683,19 +678,17 @@ void codex_client_start(CodexClient *client, const char *cwd) {
client->cwd = g_strdup(cwd ? cwd : ".");
client->cancellable = g_cancellable_new();

GError *error = NULL;
GSubprocessLauncher *launcher = g_subprocess_launcher_new(
g_autoptr(GError) error = NULL;
g_autoptr(GSubprocessLauncher) launcher = g_subprocess_launcher_new(
G_SUBPROCESS_FLAGS_STDIN_PIPE |
G_SUBPROCESS_FLAGS_STDOUT_PIPE |
G_SUBPROCESS_FLAGS_STDERR_SILENCE);
client->process = g_subprocess_launcher_spawn(launcher, &error,
"codex", "app-server",
"--stdio", NULL);
g_object_unref(launcher);
if (!client->process) {
codex_client_set_state(client, CODEX_CLIENT_FAILED,
error ? error->message : "could not start Codex");
g_clear_error(&error);
return;
}
client->input = g_object_ref(g_subprocess_get_stdin_pipe(client->process));
Expand Down
7 changes: 3 additions & 4 deletions src/codex_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,16 +605,15 @@ static void panel_revert_diff(GtkWidget *widget, gpointer user_data) {
"Reverse only the changes recorded for this Codex turn?")) {
return;
}
GError *error = NULL;
g_autoptr(GError) error = NULL;
if (codex_review_revert(panel->win, panel->turn_diff, &error)) {
g_clear_pointer(&panel->turn_diff, g_free);
gtk_widget_set_visible(panel->review_box, FALSE);
app_window_set_status(panel->win, "Codex turn reverted");
} else {
dialog_error(app_window_gtk(panel->win), "Could not revert Codex turn",
error ? error->message : "The files changed after this turn.");
app_window_set_error_status(panel->win, "Could not revert Codex turn",
error ? error->message : "The files changed after this turn.");
}
g_clear_error(&error);
}

/**
Expand Down
Loading