diff options
author | Mark Lumsden <lum@cvs.openbsd.org> | 2015-12-29 19:44:33 +0000 |
---|---|---|
committer | Mark Lumsden <lum@cvs.openbsd.org> | 2015-12-29 19:44:33 +0000 |
commit | 4fed9b0c21bdbad1e13690a53f29dea96e4e90c7 (patch) | |
tree | cdbc51ff841a19e67643934b6dc2ffd70f6b24e2 /usr.bin/mg | |
parent | e160771f9e318b591a648562d20da0aef2ed39ce (diff) |
Add transpose-words, ok jasper@.
Limited to one iteration until 'undo' is looked into.
Diffstat (limited to 'usr.bin/mg')
-rw-r--r-- | usr.bin/mg/def.h | 3 | ||||
-rw-r--r-- | usr.bin/mg/funmap.c | 3 | ||||
-rw-r--r-- | usr.bin/mg/keymap.c | 4 | ||||
-rw-r--r-- | usr.bin/mg/mg.1 | 8 | ||||
-rw-r--r-- | usr.bin/mg/word.c | 162 |
5 files changed, 173 insertions, 7 deletions
diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h index 01747539847..21bc78cb4fd 100644 --- a/usr.bin/mg/def.h +++ b/usr.bin/mg/def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: def.h,v 1.152 2015/10/29 19:46:47 lum Exp $ */ +/* $OpenBSD: def.h,v 1.153 2015/12/29 19:44:32 lum Exp $ */ /* This file is in the public domain. */ @@ -602,6 +602,7 @@ int capword(int, int); int delfword(int, int); int delbword(int, int); int inword(void); +int transposeword(int, int); /* region.c X */ int killregion(int, int); diff --git a/usr.bin/mg/funmap.c b/usr.bin/mg/funmap.c index 2571526897b..f3003582844 100644 --- a/usr.bin/mg/funmap.c +++ b/usr.bin/mg/funmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: funmap.c,v 1.51 2015/09/26 15:03:15 lum Exp $ */ +/* $OpenBSD: funmap.c,v 1.52 2015/12/29 19:44:32 lum Exp $ */ /* This file is in the public domain */ @@ -201,6 +201,7 @@ static struct funmap functnames[] = { {togglereadonly, "toggle-read-only" }, {twiddle, "transpose-chars",}, {transposepara, "transpose-paragraphs",}, + {transposeword, "transpose-words",}, {undo, "undo",}, {undo_add_boundary, "undo-boundary",}, {undo_boundary_enable, "undo-boundary-toggle",}, diff --git a/usr.bin/mg/keymap.c b/usr.bin/mg/keymap.c index 82a35dba117..ef71f845db9 100644 --- a/usr.bin/mg/keymap.c +++ b/usr.bin/mg/keymap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: keymap.c,v 1.57 2015/09/26 21:51:58 jasper Exp $ */ +/* $OpenBSD: keymap.c,v 1.58 2015/12/29 19:44:32 lum Exp $ */ /* This file is in the public domain. */ @@ -282,7 +282,7 @@ static PF metal[] = { fillpara, /* q */ backsearch, /* r */ forwsearch, /* s */ - rescan, /* t */ + transposeword, /* t */ upperword, /* u */ backpage, /* v */ copyregion, /* w */ diff --git a/usr.bin/mg/mg.1 b/usr.bin/mg/mg.1 index e3130d9d858..b5e6741979a 100644 --- a/usr.bin/mg/mg.1 +++ b/usr.bin/mg/mg.1 @@ -1,7 +1,7 @@ -.\" $OpenBSD: mg.1,v 1.98 2015/12/24 09:07:47 lum Exp $ +.\" $OpenBSD: mg.1,v 1.99 2015/12/29 19:44:32 lum Exp $ .\" This file is in the public domain. .\" -.Dd $Mdocdate: December 24 2015 $ +.Dd $Mdocdate: December 29 2015 $ .Dt MG 1 .Os .Sh NAME @@ -306,6 +306,8 @@ fill-paragraph search-backward .It M-s search-forward +.It M-t +transpose-words .It M-u upcase-word .It M-v @@ -881,6 +883,8 @@ If multiple iterations are requested, the current paragraph will be moved .Va n paragraphs forward. +.It transpose-words +Transpose adjacent words. .It undo Undo the most recent action. If invoked again without an intervening command, diff --git a/usr.bin/mg/word.c b/usr.bin/mg/word.c index fdcfa42f16b..dd1bf349076 100644 --- a/usr.bin/mg/word.c +++ b/usr.bin/mg/word.c @@ -1,4 +1,4 @@ -/* $OpenBSD: word.c,v 1.17 2015/03/19 21:22:15 bcallah Exp $ */ +/* $OpenBSD: word.c,v 1.18 2015/12/29 19:44:32 lum Exp $ */ /* This file is in the public domain. */ @@ -10,11 +10,15 @@ #include <sys/queue.h> #include <signal.h> +#include <errno.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include "def.h" RSIZE countfword(void); +int grabword(char **); /* * Move the cursor backward by "n" words. All of the details of motion are @@ -65,6 +69,162 @@ forwword(int f, int n) } /* + * Transpose 2 words. + * The function below is artifically restricted to only a maximum of 1 iteration + * at the moment because the 'undo' functionality within mg needs amended for + * multiple movements of point, backwards and forwards. + */ +int +transposeword(int f, int n) +{ + struct line *tmp1_w_dotp = NULL; + struct line *tmp2_w_dotp = NULL; + int tmp2_w_doto = 0; + int tmp1_w_dotline = 0; + int tmp2_w_dotline = 0; + int tmp1_w_doto; + int i; /* start-of-line space counter */ + int ret, s; + int newline; + int leave = 0; + int tmp_len; + char *word1 = NULL; + char *word2 = NULL; + char *chr; + + if (n == 0) + return (TRUE); + + n = 1; /* remove this line to allow muliple-iterations */ + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + dobeep(); + ewprintf("Buffer is read-only"); + return (FALSE); + } + undo_boundary_enable(FFRAND, 0); + + /* go backwards to find the start of a word to transpose. */ + (void)backword(FFRAND, 1); + ret = grabword(&word1); + if (ret == ABORT) { + ewprintf("No word to the left to tranpose."); + return (FALSE); + } + if (ret < 0) { + dobeep(); + ewprintf("Error copying word: %s", strerror(ret)); + free(word1); + return (FALSE); + } + tmp_len = strlen(word1); + + while (n-- > 0) { + i = 0; + newline = 0; + + tmp1_w_doto = curwp->w_doto; + tmp1_w_dotline = curwp->w_dotline; + tmp1_w_dotp = curwp->w_dotp; + + /* go forward and find next word. */ + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) { + leave = 1; + if (tmp1_w_dotline < curwp->w_dotline) + curwp->w_dotline--; + ewprintf("Don't have two things to transpose"); + break; + } + if (curwp->w_doto == 0) { + newline = 1; + i = 0; + } else if (newline) + i++; + } + if (leave) { + tmp2_w_doto = tmp1_w_doto; + tmp2_w_dotline = tmp1_w_dotline; + tmp2_w_dotp = tmp1_w_dotp; + break; + } + tmp2_w_doto = curwp->w_doto; + tmp2_w_dotline = curwp->w_dotline; + tmp2_w_dotp = curwp->w_dotp; + + ret = grabword(&word2); + if (ret < 0) { + dobeep(); + ewprintf("Error copying word: %s", strerror(ret)); + free(word1); + return (FALSE); + } + tmp_len = strlen(word2); + tmp2_w_doto += tmp_len; + + curwp->w_doto = tmp1_w_doto; + curwp->w_dotline = tmp1_w_dotline; + curwp->w_dotp = tmp1_w_dotp; + + /* insert shuffled along word */ + for (chr = word2; *chr != '\0'; ++chr) + linsert(1, *chr); + + if (newline) + tmp2_w_doto = i; + + curwp->w_doto = tmp2_w_doto; + curwp->w_dotline = tmp2_w_dotline; + curwp->w_dotp = tmp2_w_dotp; + + word2 = NULL; + } + curwp->w_doto = tmp2_w_doto; + curwp->w_dotline = tmp2_w_dotline; + curwp->w_dotp = tmp2_w_dotp; + + /* insert very first word in its new position */ + for (chr = word1; *chr != '\0'; ++chr) + linsert(1, *chr); + + if (leave) + (void)backword(FFRAND, 1); + + free(word1); + free(word2); + + undo_boundary_enable(FFRAND, 1); + + return (TRUE); +} + +/* + * copy and delete word. +*/ +int +grabword(char **word) +{ + int c; + + while (inword() == TRUE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (*word == NULL) { + if (asprintf(word, "%c", c) == -1) + return (errno); + } else { + if (asprintf(word, "%s%c", *word, c) == -1) + return (errno); + } + (void)forwdel(FFRAND, 1); + } + if (*word == NULL) + return (ABORT); + return (TRUE); +} + +/* * Move the cursor forward by the specified number of words. As you move, * convert any characters to upper case. */ |