From 908a22e41ce9b33156ee2fa7a68bd585033cf3a3 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 31 Jan 2012 15:52:21 +0000 Subject: [PATCH] Provide defined ways to set the various default-path possibilities: ~ for home directory, . for server start directory, - for session start directory and empty for the pane's working directory (the default). All can also be used as part of a relative path (eg -/foo). Also provide -c flags to neww and splitw to override default-path setting. Based on a diff from sthen. ok sthen --- cmd-new-window.c | 7 ++-- cmd-split-window.c | 7 ++-- cmd.c | 87 ++++++++++++++++++++++++++++++++++++---------- tmux.1 | 11 ++++++ tmux.h | 2 +- 5 files changed, 88 insertions(+), 26 deletions(-) diff --git a/cmd-new-window.c b/cmd-new-window.c index d858ee30..cf93567d 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -30,8 +30,9 @@ int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_new_window_entry = { "new-window", "neww", - "adkn:Pt:", 0, 1, - "[-adk] [-n window-name] [-t target-window] [command]", + "ac:dkn:Pt:", 0, 1, + "[-adk] [-c start-directory] [-n window-name] [-t target-window] " + "[command]", 0, NULL, NULL, @@ -99,7 +100,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = cmd_get_default_path(ctx); + cwd = cmd_get_default_path(ctx, args_get(args, 'c')); if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); diff --git a/cmd-split-window.c b/cmd-split-window.c index 05de0955..5aa0af5f 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -33,8 +33,9 @@ int cmd_split_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_split_window_entry = { "split-window", "splitw", - "dl:hp:Pt:v", 0, 1, - "[-dhvP] [-p percentage|-l size] [-t target-pane] [command]", + "c:dl:hp:Pt:v", 0, 1, + "[-dhvP] [-c start-directory] [-p percentage|-l size] [-t target-pane] " + "[command]", 0, cmd_split_window_key_binding, NULL, @@ -78,7 +79,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; - cwd = cmd_get_default_path(ctx); + cwd = cmd_get_default_path(ctx, args_get(args, 'c')); type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) diff --git a/cmd.c b/cmd.c index 9656ae4f..5e2abfec 100644 --- a/cmd.c +++ b/cmd.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -1251,34 +1252,82 @@ cmd_template_replace(char *template, const char *s, int idx) return (buf); } -/* Return the default path for a new pane. */ +/* + * Return the default path for a new pane, using the given path or the + * default-path option if it is NULL. Several special values are accepted: the + * empty string or relative path for the current pane's working directory, ~ + * for the user's home, - for the session working directory, . for the tmux + * server's working directory. The default on failure is the session's working + * directory. + */ const char * -cmd_get_default_path(struct cmd_ctx *ctx) +cmd_get_default_path(struct cmd_ctx *ctx, const char *cwd) { - const char *cwd; struct session *s; - struct window_pane *wp; struct environ_entry *envent; + const char *root; + char tmp[MAXPATHLEN]; + struct passwd *pw; + int n; + size_t skip; + static char path[MAXPATHLEN]; if ((s = cmd_current_session(ctx, 0)) == NULL) return (NULL); - cwd = options_get_string(&s->options, "default-path"); - if ((cwd[0] == '~' && cwd[1] == '\0') || !strcmp(cwd, "$HOME")) { - envent = environ_find(&global_environ, "HOME"); - if (envent != NULL && *envent->value != '\0') - return envent->value; - cwd = ""; - } - if (*cwd == '\0') { - if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) - return (ctx->cmdclient->cwd); - if (ctx->curclient != NULL) { - wp = s->curw->window->active; - if ((cwd = get_proc_cwd(wp->pid)) != NULL) - return (cwd); + if (cwd == NULL) + cwd = options_get_string(&s->options, "default-path"); + + skip = 1; + if (strcmp(cwd, "$HOME") == 0 || strncmp(cwd, "$HOME/", 6) == 0) { + /* User's home directory - $HOME. */ + skip = 5; + goto find_home; + } else if (cwd[0] == '~' && (cwd[1] == '\0' || cwd[1] == '/')) { + /* User's home directory - ~. */ + goto find_home; + } else if (cwd[0] == '-' && (cwd[1] == '\0' || cwd[1] == '/')) { + /* Session working directory. */ + root = s->cwd; + goto complete_path; + } else if (cwd[0] == '.' && (cwd[1] == '\0' || cwd[1] == '/')){ + /* Server working directory. */ + if (getcwd(tmp, sizeof tmp) != NULL) { + root = tmp; + goto complete_path; } return (s->cwd); + } else if (*cwd == '/') { + /* Absolute path. */ + return (cwd); + } else { + /* Empty or relative path. */ + if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) + root = ctx->cmdclient->cwd; + else if (ctx->curclient != NULL) + root = get_proc_cwd(s->curw->window->active->pid); + else + return (s->cwd); + skip = 0; + goto complete_path; } - return (cwd); + + return (s->cwd); + +find_home: + envent = environ_find(&global_environ, "HOME"); + if (envent != NULL && *envent->value != '\0') + root = envent->value; + else if ((pw = getpwuid(getuid())) != NULL) + root = pw->pw_dir; + else + return (s->cwd); + +complete_path: + if (root[skip] == '\0') + return (root); + n = snprintf(path, sizeof path, "%s/%s", root, cwd + skip); + if (n > 0 && (size_t)n < sizeof path) + return (path); + return (s->cwd); } diff --git a/tmux.1 b/tmux.1 index d282f1d9..e34eeb73 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1224,6 +1224,7 @@ is moved to .Ar dst-window . .It Xo Ic new-window .Op Fl adkP +.Op Fl c Ar start-directory .Op Fl n Ar window-name .Op Fl t Ar target-window .Op Ar shell-command @@ -1254,6 +1255,15 @@ If is not specified, the value of the .Ic default-command option is used. +.Fl c +specifies the working directory in which the new window is created. +It may have an absolute path or one of the following values (or a subdirectory): +.Bl -column "XXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXX" -offset indent +.It Li "Empty string" Ta "Current pane's directory" +.It Li "~" Ta "User's home directory" +.It Li "-" Ta "Where session was started" +.It Li "." Ta "Where server was started" +.El .Pp When the shell command completes, the window closes. See the @@ -1453,6 +1463,7 @@ and commands. .It Xo Ic split-window .Op Fl dhvP +.Op Fl c Ar start-directory .Oo Fl l .Ar size | .Fl p Ar percentage Oc diff --git a/tmux.h b/tmux.h index a52edf6f..1e1639de 100644 --- a/tmux.h +++ b/tmux.h @@ -1559,7 +1559,7 @@ int cmd_find_index( struct winlink *cmd_find_pane(struct cmd_ctx *, const char *, struct session **, struct window_pane **); char *cmd_template_replace(char *, const char *, int); -const char *cmd_get_default_path(struct cmd_ctx *ctx); +const char *cmd_get_default_path(struct cmd_ctx *, const char *); extern const struct cmd_entry *cmd_table[]; extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_bind_key_entry;