Skip to content

Commit

Permalink
avoid chdir in cmd_browse (#43)
Browse files Browse the repository at this point in the history
instead of `chdir`ing the entire editor process, this patch maintains
a `browse_path` string that we `cd` into (as part of the forked shell
process) before executing `tree`. this should fix the bug
@kevinsjoberg reported without changing the behavior of `cmd_browse`.
  • Loading branch information
adsr committed Aug 27, 2022
1 parent 0ad8416 commit 3253070
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 39 deletions.
1 change: 0 additions & 1 deletion bview.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ bview_t *bview_new(editor_t *editor, int type, char *opt_path, int opt_path_len,
self->viewport_scope_x = editor->viewport_scope_x;
self->viewport_scope_y = editor->viewport_scope_y;
self->id = (id++);
getcwd(self->init_cwd, PATH_MAX + 1);

// Open buffer
if (opt_buffer) {
Expand Down
61 changes: 40 additions & 21 deletions cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,13 +705,21 @@ int cmd_browse(cmd_context_t *ctx) {
bview_t *menu;
aproc_t *aproc;
char *cmd;
asprintf(&cmd, "tree --charset C -n -f -L 2 %s 2>/dev/null", ctx->static_param ? ctx->static_param : "");
char *browse_path;
browse_path = ctx->static_param ? ctx->static_param : "./";
asprintf(&cmd, "cd %s && tree --charset C -n -f -L 2 2>/dev/null", browse_path);
aproc = aproc_new(ctx->editor, ctx->bview, &(ctx->bview->aproc), cmd, 0, _cmd_aproc_bview_passthru_cb);
free(cmd);
if (!aproc) return MLE_ERR;
editor_menu(ctx->editor, _cmd_menu_browse_cb, "..\n", 3, aproc, &menu);
editor_menu(ctx->editor, _cmd_menu_browse_cb, ".", 1, aproc, &menu);
mark_move_beginning(menu->active_cursor->mark);
bview_zero_viewport_y(menu);
if (strncmp(browse_path, "./", 2) == 0) {
browse_path += 2;
} else if (strcmp(browse_path, ".") == 0) {
browse_path = "";
}
snprintf(menu->browse_path, sizeof(menu->browse_path), "%s", browse_path);
return MLE_OK;
}

Expand Down Expand Up @@ -1728,51 +1736,62 @@ static int _cmd_menu_ctag_cb(cmd_context_t *ctx) {
// Callback from cmd_browse
static int _cmd_menu_browse_cb(cmd_context_t *ctx) {
char *line;
char *path;
char cwd[PATH_MAX];
char *corrected_path;
bview_t *new_bview;
char *path, *tmp;
char apath[PATH_MAX + 1];
bview_t *new_bview, *self_bview;

// Get path from tree output
line = strndup(ctx->bview->active_cursor->mark->bline->data, ctx->bview->active_cursor->mark->bline->data_len);
if ((path = strstr(line, "- ")) != NULL) {
path += 2;
if ((path = strstr(line, "-- ")) != NULL) {
path += 3;
if (strncmp(path, "./", 2) == 0) {
path += 2;
}
if ((tmp = strstr(path, " -> ")) != NULL) {
*tmp = '\0';
}
} else if (strcmp(line, "..") == 0) {
path = "..";
} else if (util_is_dir(line)) {
path = line;
} else if (strlen(line) < 1) {
free(line);
return MLE_OK;
} else {
MLE_SET_ERR(ctx->editor, "browse: Cannot browse to: '%s'", line);
free(line);
return MLE_ERR;
}

// Fix cwd if it changed
getcwd(cwd, PATH_MAX);
if (strcmp(cwd, ctx->bview->init_cwd) != 0) {
asprintf(&corrected_path, "%s/%s", ctx->bview->init_cwd, path);
// Derive apath
size_t browse_path_len = strlen(ctx->bview->browse_path);
if (browse_path_len > 0 && *path != '/') {
snprintf(apath, sizeof(apath),
"%s%s%s",
ctx->bview->browse_path,
ctx->bview->browse_path[browse_path_len - 1] != '/' ? "/" : "",
path
);
} else {
corrected_path = strdup(path);
snprintf(apath, sizeof(apath), "%s", path);
}

// Open file or browse dir
self_bview = ctx->bview;
new_bview = NULL;
if (util_is_dir(corrected_path)) {
chdir(corrected_path);
if (util_is_dir(apath)) {
ctx->bview = ctx->editor->active_edit;
ctx->static_param = apath;
cmd_browse(ctx);
} else {
editor_open_bview(ctx->editor, NULL, MLE_BVIEW_TYPE_EDIT, corrected_path, strlen(corrected_path), 0, 0, 0, NULL, &new_bview);
editor_open_bview(ctx->editor, NULL, MLE_BVIEW_TYPE_EDIT, apath, strlen(apath), 0, 0, 0, NULL, &new_bview);
}

// Close menu
editor_close_bview(ctx->editor, ctx->bview, NULL);
// Close self
editor_close_bview(ctx->editor, self_bview, NULL);

// Set new_bview to active
if (new_bview) editor_set_active(ctx->editor, new_bview);

free(line);
free(corrected_path);

return MLE_OK;
}
Expand Down
4 changes: 1 addition & 3 deletions editor.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,10 @@ int editor_open_bview(editor_t *editor, bview_t *opt_parent, int type, char *opt
cmd_context_t ctx;
memset(&ctx, 0, sizeof(cmd_context_t));
ctx.editor = editor;
ctx.static_param = strndup(opt_path, opt_path_len);
ctx.static_param = opt_path;
ctx.bview = bview;
cmd_browse(&ctx);
editor_close_bview(editor, bview, NULL);
free(ctx.static_param);
ctx.static_param = NULL;
}
return MLE_OK;
}
Expand Down
2 changes: 1 addition & 1 deletion mle.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ struct bview_s {
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
char init_cwd[PATH_MAX + 1];
char browse_path[PATH_MAX + 1];
int id;
bview_listener_t *listeners;
bview_t *top_next;
Expand Down
22 changes: 9 additions & 13 deletions tests/func/test_browse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,19 @@ if ! command -v tree &>/dev/null; then
fi

# make tmpdir and delete at exit
this_dir=$(pwd)
tmpdir=$(mktemp -d)
pushed=0
finish() { [ $pushed -eq 1 ] && popd &>/dev/null; rm -rf $tmpdir; }
cd $tmpdir
finish() { cd $this_dir; rm -rf $tmpdir; }
trap finish EXIT

# make adir/bdir/hello
this_dir=$(pwd)
pushd $tmpdir &>/dev/null
pushed=1
# setup tmpdir
mkdir -p adir/bdir
touch adir/bdir/hello
touch adir/bdir/hi

# ensure that we can browse into adir, then bdir, then select hello
macro='C-b C-f a d i r enter enter C-f b d i r enter enter C-f h e l l o enter enter'
# ensure that we can browse into adir, bdir, then select hi
# ensure path is relative to where we started
macro='C-b C-f a d i r enter enter C-f b d i r enter enter C-f h i enter enter'
declare -A expected
expected[hello]='^bview.[[:digit:]]+.buffer.path=./hello$'
expected[hi]='^bview.[[:digit:]]+.buffer.path=adir/bdir/hi$'
source "$this_dir/test.sh"

popd &>/dev/null
pushed=0

0 comments on commit 3253070

Please sign in to comment.