Forgive me for sending so many email.
I've rewritten code again one last time. I'm not sure if this is correct.
I was able to learn shell through these emails. I really appreciate it.
Best regards,
Hajime Edakawa
Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.85
diff -u -p -r1.85 emacs.c
--- emacs.c 18 Jun 2018 17:03:58 -0000 1.85
+++ emacs.c 13 Oct 2018 06:04:46 -0000
@@ -201,6 +201,7 @@ static int x_fold_lower(int);
static int x_fold_upper(int);
static int x_set_arg(int);
static int x_comment(int);
+static int x_expand_alias_sub(int);
#ifdef DEBUG
static int x_debug_info(int);
#endif
@@ -258,6 +259,7 @@ static const struct x_ftab x_ftab[] = {
{ x_fold_upper, "upcase-word", XF_ARG },
{ x_set_arg, "set-arg", XF_NOBIND },
{ x_comment, "comment", 0 },
+ { x_expand_alias_sub, "expand-alias-substitute", 0 },
{ 0, 0, 0 },
#ifdef DEBUG
{ x_debug_info, "debug-info", 0 },
@@ -1492,6 +1494,7 @@ x_init_emacs(void)
kb_add(x_comp_file, CTRL('['), CTRL('X'), 0);
kb_add(x_comp_list, CTRL('I'), 0);
kb_add(x_comp_list, CTRL('['), '=', 0);
+ kb_add(x_expand_alias_sub, CTRL('['), CTRL('E'), 0);
kb_add(x_del_back, CTRL('?'), 0);
kb_add(x_del_back, CTRL('H'), 0);
kb_add(x_del_char, CTRL('['), '[', '3', '~', 0);
/* delete */
@@ -1982,6 +1985,95 @@ x_comment(int c)
return KSTD;
}
+static int
+x_expand_alias_sub(int c)
+{
+ struct tbl *tp;
+ Area *saved_atemp;
+ const char *sep = str_val(local("IFS", 0));
+ char s[2];
+ char *cp;
+ char *begin, *word;
+ char *tmp, *tok, *state;
+ char *input, *output;
+ int skip = 0;
+ int ch, bufsize;
+ size_t len = 0;
+
+ if (xep == xbuf) {
+ x_e_putc(BEL);
+ return KSTD;
+ }
+
+ cp = xbuf;
+ while (cp != xep && ctype(*cp, C_IFSWS))
+ skip += x_size(*cp++);
+
+ begin = cp;
+ if (cp != xep && letter(*cp)) {
+ cp++;
+ len++;
+ while (cp != xep && letnum(*cp)) {
+ cp++;
+ len++;
+ }
+ }
+
+ if (len > 0) {
+ word = str_nsave(begin, len, ATEMP);
+ tp = ktsearch(&aliases, word, hash(word));
+ if (tp && (tp->flag & ISSET)) {
+ tmp = str_save(tp->val.s, ATEMP);
+ tok = strtok_r(tmp, sep, &state);
+ if (tok && strcmp(word, tok)) {
+ x_goto(xbuf + skip);
+ x_delete(len, false);
+ x_ins(tp->val.s);
+ }
+ afree(tmp, ATEMP);
+ }
+ afree(word, ATEMP);
+ }
+
+ input = str_save(xbuf, ATEMP);
+ saved_atemp = ATEMP;
+ newenv(E_ERRH);
+ if (sigsetjmp(genv->jbuf, 0))
+ output = NULL;
+ else
+ output = str_save(substitute(input, 0), saved_atemp);
+ quitenv(NULL);
+
+ if (!output) {
+ x_e_putc(BEL);
+ return KSTD;
+ }
+
+ bufsize = x_size_str(xbuf);
+ x_goto(xbuf);
+ x_delete(bufsize, false);
+
+ s[0] = ' ';
+ s[1] = '\0';
+ while (isspace((unsigned char)*output)) {
+ output++;
+ x_ins(s);
+ }
+
+ while ((ch = *output++)) {
+ if (isprint(ch)) {
+ s[0] = ch;
+ s[1] = '\0';
+ x_ins(s);
+ } else if (ch == '\r' || ch == '\n') {
+ s[0] = ' ';
+ s[1] = '\0';
+ x_ins(s);
+ }
+ }
+
+ return KSTD;
+}
/* NAME:
* x_prev_histword - recover word from prev command
>
> I send the email once again because missing tab space.
> I'm sorry that to send extra email.
>
> Index: emacs.c
> ===================================================================
> RCS file: /cvs/src/bin/ksh/emacs.c,v
> retrieving revision 1.85
> diff -u -p -r1.85 emacs.c
> --- emacs.c 18 Jun 2018 17:03:58 -0000 1.85
> +++ emacs.c 10 Oct 2018 23:26:49 -0000
> @@ -201,6 +201,7 @@ static int x_fold_lower(int);
> static int x_fold_upper(int);
> static int x_set_arg(int);
> static int x_comment(int);
> +static int x_expand_alias_sub(int);
> #ifdef DEBUG
> static int x_debug_info(int);
> #endif
> @@ -258,6 +259,7 @@ static const struct x_ftab x_ftab[] = {
> { x_fold_upper, "upcase-word", XF_ARG },
> { x_set_arg, "set-arg", XF_NOBIND },
> { x_comment, "comment", 0 },
> + { x_expand_alias_sub, "expand-alias-substitute", 0 },
> { 0, 0, 0 },
> #ifdef DEBUG
> { x_debug_info, "debug-info", 0 },
> @@ -1492,6 +1494,7 @@ x_init_emacs(void)
> kb_add(x_comp_file, CTRL('['), CTRL('X'), 0);
> kb_add(x_comp_list, CTRL('I'), 0);
> kb_add(x_comp_list, CTRL('['), '=', 0);
> + kb_add(x_expand_alias_sub, CTRL('['), CTRL('E'), 0);
> kb_add(x_del_back, CTRL('?'), 0);
> kb_add(x_del_back, CTRL('H'), 0);
> kb_add(x_del_char, CTRL('['), '[', '3', '~', 0);
> /* delete */
> @@ -1982,6 +1985,73 @@ x_comment(int c)
> return KSTD;
> }
>
> +static int
> +x_expand_alias_sub(int c)
> +{
> + struct tbl *tp;
> + const char *sep = " \t\n";
> + char *cp;
> + char *word, *name;
> + char *buf, *tok, *state;
> + int skip = 0;
> + int size = 0;
> + size_t len = 0;
> +
> + if (xep == xbuf)
> + goto fail;
> +
> + cp = xbuf;
> + while (cp != xep && is_mfs(*cp))
> + skip += x_size(*cp++);
> +
> + word = cp;
> + while (cp != xep && !is_mfs(*cp)) {
> + size += x_size(*cp++);
> + len++;
> + }
> +
> + if (len > 0) {
> + name = strndup(word, len);
> + if (!name) {
> + bi_errorf("unable to allocate memory");
> + goto fail;
> + }
> +
> + tp = ktsearch(&aliases, name, hash(name));
> + if (tp) {
> + buf = strdup(tp->val.s);
> + if (!buf) {
> + bi_errorf("unable to allocate memory");
> + goto fail;
> + }
> +
> + tok = strtok_r(buf, sep, &state);
> + if (!tok) {
> + bi_errorf("strtok_r failed");
> + goto fail;
> + }
> +
> + if (strcmp(name, tok)) {
> + x_goto(xbuf + skip);
> + x_delete(size, false);
> + x_ins(tp->val.s);
> + }
> + }
> + }
> +
> + size = x_size_str(xbuf);
> + buf = substitute(xbuf, 0);
> +
> + x_goto(xbuf);
> + x_delete(size, false);
> + x_ins(buf);
> + x_adjust();
> +
> + return KSTD;
> +fail:
> + x_e_putc(BEL);
> + return KSTD;
> +}
>
> /* NAME:
> * x_prev_histword - recover word from prev command
>
> 2018年10月11日(木) 10:07 Hajime Edakawa <[email protected]>:
> >
> > Klemens Nanni wrote:
> > >Thanks for your work.
> >
> > I'm the one who should be thanking OpenBSD developers.
> > It's a real honor to hear that!
> >
> > >With `alias ls=ls\ -l' and successive expand-line invocations: will
> > >`ls' be expanded over and over again?
> >
> > Maybe I fixed the problems that you pointed out.
> >
> > $ type ls
> > ls is an alias for 'ls -CF'
> > $ alias ll='ls -l'
> > $ ll
> > $ ls -l
> > $ ls -l
> > ...
> >
> > >This looks nice.
> >
> > I added some more example.
> >
> > $ path=/foo/bar/file.txt
> > $ alias ll='ls -l'
> > $ ll "$(echo $$)" $(( 1 + 1 )) ${path##*/} hoge
> > $ ls -l "71788" 2 file.txt hoge
> >
> > >Did you test it in vi mode as well?
> >
> > Unfortunately, I've never use vi. I'm really sorry.
> > I'd like to study vi sometime.
> >
> > >Your diff does not apply to -CURRENT (written against 6.3) and lacks
> > >documentation updates to ksh(1).
> >
> > I've tried to add the diff of emacs.c and ksh.1 against -CURRENT.
> > The name changes from shell-expand-line to expand-alias-substitute.
> > And expand-alias-substitute code was modified.
> >
> > /* Excuse me if you not understand or you feel bad with my poor English */
> >
> > Best regards,
> > Hajime Edakawa
> >
> > Index: ksh.1
> > ===================================================================
> > RCS file: /cvs/src/bin/ksh/ksh.1,v
> > retrieving revision 1.201
> > diff -u -p -r1.201 ksh.1
> > --- ksh.1 18 Jun 2018 17:03:58 -0000 1.201
> > +++ ksh.1 10 Oct 2018 23:26:57 -0000
> > @@ -4819,6 +4819,10 @@ if alone on a line; otherwise acts as
> > Error (ring the bell).
> > .It exchange-point-and-mark: ^X^X
> > Places the cursor where the mark is and sets the mark to where the cursor
> > was.
> > +.It expand-alias-substitute: ^[^E
> > +Automatically expands a command alias and substitute parameter,
> > command, and arithmetic (see
> > +.Sx Substitution
> > +below).
> > .It expand-file: ^[*
> > Appends a
> > .Ql *
> > Index: emacs.c
> > ===================================================================
> > RCS file: /cvs/src/bin/ksh/emacs.c,v
> > retrieving revision 1.85
> > diff -u -p -r1.85 emacs.c
> > --- emacs.c 18 Jun 2018 17:03:58 -0000 1.85
> > +++ emacs.c 10 Oct 2018 23:26:49 -0000
> > @@ -201,6 +201,7 @@ static int x_fold_lower(int);
> > static int x_fold_upper(int);
> > static int x_set_arg(int);
> > static int x_comment(int);
> > +static int x_expand_alias_sub(int);
> > #ifdef DEBUG
> > static int x_debug_info(int);
> > #endif
> > @@ -258,6 +259,7 @@ static const struct x_ftab x_ftab[] = {
> > { x_fold_upper, "upcase-word", XF_ARG },
> > { x_set_arg, "set-arg", XF_NOBIND },
> > { x_comment, "comment", 0 },
> > + { x_expand_alias_sub, "expand-alias-substitute", 0 },
> > { 0, 0, 0 },
> > #ifdef DEBUG
> > { x_debug_info, "debug-info", 0 },
> > @@ -1492,6 +1494,7 @@ x_init_emacs(void)
> > kb_add(x_comp_file, CTRL('['), CTRL('X'), 0);
> > kb_add(x_comp_list, CTRL('I'), 0);
> > kb_add(x_comp_list, CTRL('['), '=', 0);
> > + kb_add(x_expand_alias_sub, CTRL('['), CTRL('E'), 0);
> > kb_add(x_del_back, CTRL('?'), 0);
> > kb_add(x_del_back, CTRL('H'), 0);
> > kb_add(x_del_char, CTRL('['), '[', '3', '~', 0); /* delete */
> > @@ -1982,6 +1985,73 @@ x_comment(int c)
> > return KSTD;
> > }
> >
> > +static int
> > +x_expand_alias_sub(int c)
> > +{
> > + struct tbl *tp;
> > + const char *sep = " \t\n";
> > + char *cp;
> > + char *word, *name;
> > + char *buf, *tok, *state;
> > + int skip = 0;
> > + int size = 0;
> > + size_t len = 0;
> > +
> > + if (xep == xbuf)
> > + goto fail;
> > +
> > + cp = xbuf;
> > + while (cp != xep && is_mfs(*cp))
> > + skip += x_size(*cp++);
> > +
> > + word = cp;
> > + while (cp != xep && !is_mfs(*cp)) {
> > + size += x_size(*cp++);
> > + len++;
> > + }
> > +
> > + if (len > 0) {
> > + name = strndup(word, len);
> > + if (!name) {
> > + bi_errorf("unable to allocate memory");
> > + goto fail;
> > + }
> > +
> > + tp = ktsearch(&aliases, name, hash(name));
> > + if (tp) {
> > + buf = strdup(tp->val.s);
> > + if (!buf) {
> > + bi_errorf("unable to allocate memory");
> > + goto fail;
> > + }
> > +
> > + tok = strtok_r(buf, sep, &state);
> > + if (!tok) {
> > + bi_errorf("strtok_r failed");
> > + goto fail;
> > + }
> > +
> > + if (strcmp(name, tok)) {
> > + x_goto(xbuf + skip);
> > + x_delete(size, false);
> > + x_ins(tp->val.s);
> > + }
> > + }
> > + }
> > +
> > + size = x_size_str(xbuf);
> > + buf = substitute(xbuf, 0);
> > +
> > + x_goto(xbuf);
> > + x_delete(size, false);
> > + x_ins(buf);
> > + x_adjust();
> > +
> > + return KSTD;
> > +fail:
> > + x_e_putc(BEL);
> > + return KSTD;
> > +}
> >
> > /* NAME:
> > * x_prev_histword - recover word from prev command
> > 2018年10月11日(木) 2:52 Klemens Nanni <[email protected]>:
> > >
> > > On Wed, Oct 10, 2018 at 08:58:43AM +0900, Hajime Edakawa wrote:
> > > > I have challenged to try to make shell_expand_line in ksh.
> > > > You can check it if you type M-C-e.
> > > Thanks for your work.
> > >
> > > > $ echo "$(echo a b)"
> > > > $ echo "a b"
> > > >
> > > > $ alias ll='ls -l'
> > > > $ ll $(echo a b) hoge "$(( 1 + 1 ))" ll bar
> > > > $ ls -l a b hoge "2" ll bar
> > > This looks nice.
> > >
> > > With `alias ls=ls\ -l' and successive expand-line invocations: will
> > > `ls' be expanded over and over again?
> > >
> > > Did you test it in vi mode as well?
> > >
> > > > To be honest, I'm not sure if this is correct.
> > > > I only like OpenBSD, That's why I'm so sorry if they're wrong
> > > Your diff does not apply to -CURRENT (written against 6.3) and lacks
> > > documentation updates to ksh(1).