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).

Reply via email to