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
pull/1/head
Nicholas Marriott 2012-01-31 15:52:21 +00:00
parent 49a5a587ec
commit 908a22e41c
5 changed files with 88 additions and 26 deletions

View File

@ -30,8 +30,9 @@ int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_new_window_entry = { const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "new-window", "neww",
"adkn:Pt:", 0, 1, "ac:dkn:Pt:", 0, 1,
"[-adk] [-n window-name] [-t target-window] [command]", "[-adk] [-c start-directory] [-n window-name] [-t target-window] "
"[command]",
0, 0,
NULL, NULL,
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"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; cmd = args->argv[0];
cwd = cmd_get_default_path(ctx); cwd = cmd_get_default_path(ctx, args_get(args, 'c'));
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(&s->options, "base-index");

View File

@ -33,8 +33,9 @@ int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_split_window_entry = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
"dl:hp:Pt:v", 0, 1, "c:dl:hp:Pt:v", 0, 1,
"[-dhvP] [-p percentage|-l size] [-t target-pane] [command]", "[-dhvP] [-c start-directory] [-p percentage|-l size] [-t target-pane] "
"[command]",
0, 0,
cmd_split_window_key_binding, cmd_split_window_key_binding,
NULL, NULL,
@ -78,7 +79,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
else else
cmd = args->argv[0]; cmd = args->argv[0];
cwd = cmd_get_default_path(ctx); cwd = cmd_get_default_path(ctx, args_get(args, 'c'));
type = LAYOUT_TOPBOTTOM; type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h')) if (args_has(args, 'h'))

87
cmd.c
View File

@ -21,6 +21,7 @@
#include <fnmatch.h> #include <fnmatch.h>
#include <paths.h> #include <paths.h>
#include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -1251,34 +1252,82 @@ cmd_template_replace(char *template, const char *s, int idx)
return (buf); 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 * 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 session *s;
struct window_pane *wp;
struct environ_entry *envent; 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) if ((s = cmd_current_session(ctx, 0)) == NULL)
return (NULL); return (NULL);
cwd = options_get_string(&s->options, "default-path"); if (cwd == NULL)
if ((cwd[0] == '~' && cwd[1] == '\0') || !strcmp(cwd, "$HOME")) { cwd = options_get_string(&s->options, "default-path");
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0') skip = 1;
return envent->value; if (strcmp(cwd, "$HOME") == 0 || strncmp(cwd, "$HOME/", 6) == 0) {
cwd = ""; /* User's home directory - $HOME. */
} skip = 5;
if (*cwd == '\0') { goto find_home;
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) } else if (cwd[0] == '~' && (cwd[1] == '\0' || cwd[1] == '/')) {
return (ctx->cmdclient->cwd); /* User's home directory - ~. */
if (ctx->curclient != NULL) { goto find_home;
wp = s->curw->window->active; } else if (cwd[0] == '-' && (cwd[1] == '\0' || cwd[1] == '/')) {
if ((cwd = get_proc_cwd(wp->pid)) != NULL) /* Session working directory. */
return (cwd); 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); 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);
} }

11
tmux.1
View File

@ -1224,6 +1224,7 @@ is moved to
.Ar dst-window . .Ar dst-window .
.It Xo Ic new-window .It Xo Ic new-window
.Op Fl adkP .Op Fl adkP
.Op Fl c Ar start-directory
.Op Fl n Ar window-name .Op Fl n Ar window-name
.Op Fl t Ar target-window .Op Fl t Ar target-window
.Op Ar shell-command .Op Ar shell-command
@ -1254,6 +1255,15 @@ If
is not specified, the value of the is not specified, the value of the
.Ic default-command .Ic default-command
option is used. 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 .Pp
When the shell command completes, the window closes. When the shell command completes, the window closes.
See the See the
@ -1453,6 +1463,7 @@ and
commands. commands.
.It Xo Ic split-window .It Xo Ic split-window
.Op Fl dhvP .Op Fl dhvP
.Op Fl c Ar start-directory
.Oo Fl l .Oo Fl l
.Ar size | .Ar size |
.Fl p Ar percentage Oc .Fl p Ar percentage Oc

2
tmux.h
View File

@ -1559,7 +1559,7 @@ int cmd_find_index(
struct winlink *cmd_find_pane(struct cmd_ctx *, struct winlink *cmd_find_pane(struct cmd_ctx *,
const char *, struct session **, struct window_pane **); const char *, struct session **, struct window_pane **);
char *cmd_template_replace(char *, const char *, int); 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_table[];
extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_bind_key_entry;