diff --git a/ANNOUNCE b/ANNOUNCE index 58a4dd93dd7a..161e13291990 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -17,6 +17,11 @@ New command line editor features: - In the emacs line editor, pressing ^U (kill) twice no longer causes further ^U presses to start a new line (this was a feature for paper terminals). +- The ^X^E (emacs mode) and v (vi mode) commands will now only execute the + command line that was loaded into the editor if the temporary file is + saved before exiting the editor. This removes the need to empty the file + and save just to cancel execution. + New shell language features: - The appending redirection operator &>>FILE is now available. It is a @@ -44,6 +49,18 @@ New features in built-in commands: command given that was not found on PATH, and return a non-zero exit status if any of the commands given were not found. +- The 'fc'/'hist' command has a new -E option. If given and a full-screen + editor is launched, the command line that was loaded into the editor will + only be executed if the temporary file is saved before exiting the editor. + This removes the need to empty the file and save just to cancel execution. + People who want the new behaviour as a default for the fc/hist command + where available (i.e., for ksh 93u+m/1.1 and later) can add the following + to their ~/.kshrc or other profile script: + case ${KSH_VERSION-} in + *93u+m/1.0.*) ;; + *93u+m/*) alias fc='fc -E' hist='fc -E' ;; + esac + New features in shell options: - A new --arrowkeysearch option, on by default, causes the up and down arrow diff --git a/NEWS b/NEWS index 47f64e55e9c6..5031c8164b5d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,16 @@ This documents significant changes in the dev branch of ksh 93u+m. For full details, see the git log at: https://github.com/ksh93/ksh Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. +2024-12-24: + +- [v1.1] The fc/hist command has a new -E option. If this option is given, + the command line that was loaded into the editor will only be executed if + the temp file is saved before exiting the editor. + +- [v1.1] The ^X^E (emacs mode) and v (vi mode) commands will now only + execute the command line that was loaded into the full-screen editor if + the temp file is saved before exiting the editor. + 2024-12-22: - In the emacs/gmacs line editor, the ESC [ macro feature, which is diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile index a0bff1cf5ae2..6a700b16c5bd 100644 --- a/src/cmd/ksh93/Mamfile +++ b/src/cmd/ksh93/Mamfile @@ -406,6 +406,7 @@ make install virtual prev include/io.h prev include/variables.h prev %{INCLUDE_AST}/error.h + prev %{INCLUDE_AST}/tv.h prev %{INCLUDE_AST}/ls.h prev include/defs.h prev shopt.h diff --git a/src/cmd/ksh93/bltins/hist.c b/src/cmd/ksh93/bltins/hist.c index 8a69ce12c5b5..fb8f439a7e5b 100644 --- a/src/cmd/ksh93/bltins/hist.c +++ b/src/cmd/ksh93/bltins/hist.c @@ -18,6 +18,7 @@ #include "shopt.h" #include "defs.h" #include +#include #include #include "variables.h" #include "io.h" @@ -52,6 +53,7 @@ int b_hist(int argc,char *argv[], Shbltin_t *context) #if SHOPT_HISTEXPAND int pflag = 0; #endif + int checktime = 0; Histloc_t location; NOT_USED(argc); NOT_USED(context); @@ -63,6 +65,9 @@ int b_hist(int argc,char *argv[], Shbltin_t *context) hp = sh.hist_ptr; while((flag = optget(argv,sh_opthist))) switch(flag) { + case 'E': + checktime = 1; + break; case 'e': edit = opt_info.arg; break; @@ -246,11 +251,25 @@ int b_hist(int argc,char *argv[], Shbltin_t *context) } if(*arg != '-') { + int e = 0; /* error flag */ + struct stat statb; + Tv_t before, after; char *com[3]; com[0] = arg; com[1] = fname; com[2] = 0; - error_info.errors = sh_eval(sh_sfeval(com),0); + if (checktime && !(e = stat(fname,&statb)<0)) + tvgetmtime(&before,&statb); + /* invoke the editor */ + if (!e) + e = sh_eval(sh_sfeval(com),0); + if (checktime && !e && !(e = stat(fname,&statb)<0)) + { + /* if the file's timestamp hasn't changed, treat this as an error */ + tvgetmtime(&after,&statb); + e = before.tv_sec==after.tv_sec && before.tv_nsec==after.tv_nsec; + } + error_info.errors = e; } fdo = sh_chkopen(fname); unlink(fname); diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c index 71ea688b81b7..ff78aa2caa17 100644 --- a/src/cmd/ksh93/data/builtins.c +++ b/src/cmd/ksh93/data/builtins.c @@ -1017,7 +1017,7 @@ const char sh_opthash[] = #if !SHOPT_SCRIPTONLY const char sh_opthist[] = -"[-1cn?\n@(#)$Id: hist (AT&T Research) 2000-04-02 $\n]" +"[-1cn?\n@(#)$Id: hist (ksh 93u+m) 2024-12-23 $\n]" "[--catalog?" SH_DICT "]" "[+NAME?\f?\f - process command history list]" "[+DESCRIPTION?\b\f?\f\b lists, edits, or re-executes, commands " @@ -1055,6 +1055,8 @@ const char sh_opthist[] = "[+?If no editor is specified, then the editor specified by the \bHISTEDIT\b " "variable will be used if set, or the \bFCEDIT\b variable will be " "used if set, otherwise, \bed\b will be used.]" +"[E?Only execute the edited command line if the file is saved before " + "exiting the editor.]" "[e]:[editor?\aeditor\a specifies the editor to use to edit the history " "command. A value of \b-\b for \aeditor\a is equivalent to " "specifying the \b-s\b option.]" diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c index 3d193e20460c..75dfa39166a1 100644 --- a/src/cmd/ksh93/data/msg.c +++ b/src/cmd/ksh93/data/msg.c @@ -39,7 +39,7 @@ /* error messages */ const char e_timewarn[] = "\r\n\ashell will timeout in 60 seconds due to inactivity"; -const char e_runvi[] = "\\hist -e \"${VISUAL:-${EDITOR:-vi}}\" "; +const char e_runvi[] = "\\command fc -Ee\"${VISUAL:-${EDITOR:-vi}}\" "; const char e_timeout[] = "timed out waiting for input"; const char e_mailmsg[] = "you have mail in $_"; const char e_query[] = "no query process"; diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 9ab358a64860..660dc1f8b770 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #include #include "git.h" -#define SH_RELEASE_DATE "2024-12-22" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2024-12-24" /* must be in this format for $((.sh.version)) */ /* * This comment keeps SH_RELEASE_DATE a few lines away from SH_RELEASE_SVER to avoid * merge conflicts when cherry-picking dev branch commits onto a release branch. diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 8c8110a064fd..b2161945c7c7 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -5353,11 +5353,16 @@ Kill the entire current line. Restore last item removed from line. (Yank item back to the line.) .TP 10 .BI ^X^E -Return the command -.BI "hist \-e ${\s-1VISUAL\s+1:\-${\s-1EDITOR\s+1:\-vi}}" -in the input buffer to call a full editor \(em -.BI vi -by default \(em on the current command line. +Edit the current command line in a full editor (as set in the +.SM +.B VISUAL +or +.SM +.B EDITOR +variable, or +.IR vi (1), +in that order of preference). +The command line is executed if the file is saved before exiting the editor. .TP 10 .BI ^L Line feed and print current line. @@ -6113,14 +6118,21 @@ Undo the last text modifying command. Undo all the text modifying commands performed on the line. .TP 10 [\f2count\fP]\f3v\fP -Returns the command -.BI "hist \-e ${\s-1VISUAL\s+1:\-${\s-1EDITOR\s+1:\-vi}}" " count" -in the input buffer to call a full editor \(em -.BI vi -by default \(em on a history entry. +Edit command line number +.I count\^ +in a full editor (as set in the +.SM +.B VISUAL +or +.SM +.B EDITOR +variable, or +.IR vi (1), +in that order of preference). If .I count\^ is omitted, then the current line is used. +The command line is executed if the file is saved before exiting the editor. .TP 10 .BI ^L Line feed and print current line. @@ -6783,7 +6795,7 @@ Does nothing, and exits 1. Used with for infinite loops. .TP .PD 0 -\f3fc\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-N\fP \f2num\^\fP \*(CK \*(OK \f3\-nlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK +\f3fc\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-N\fP \f2num\^\fP \*(CK \*(OK \f3\-Enlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK .TP \f3fc \-s \fP \*(OK \f2old\fP\f3\=\fP\f2new\^\fP \*(CK \*(OK \f2command\^\fP \*(CK .PD @@ -6952,7 +6964,7 @@ option empties the hash table. This can also be achieved by resetting .BR PATH. .TP .PD 0 -\f3hist\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-N\fP \f2num\^\fP \*(CK \*(OK \f3\-nlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK +\f3hist\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-N\fP \f2num\^\fP \*(CK \*(OK \f3\-Enlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK .TP \f3hist \-s\fP \*(OK \f2old\fP\f3\=\fP\f2new\^\fP \*(CK \*(OK \f2command\^\fP \*(CK .PD @@ -6997,8 +7009,11 @@ is not set, then (default .BR /bin/ed\^ ) is used as the editor. -When editing is complete, the edited command(s) -is executed if the changes have been saved. +When the editor exits, the contents of the file become +the new command line and it is either executed +regardless of any change, or if the +.B \-E +option is given, it is executed if the file has been saved. If .I last\^ is not specified,