summaryrefslogtreecommitdiff
path: root/usr.bin/mg
diff options
context:
space:
mode:
authorMark Lumsden <lum@cvs.openbsd.org>2015-12-29 19:44:33 +0000
committerMark Lumsden <lum@cvs.openbsd.org>2015-12-29 19:44:33 +0000
commit4fed9b0c21bdbad1e13690a53f29dea96e4e90c7 (patch)
treecdbc51ff841a19e67643934b6dc2ffd70f6b24e2 /usr.bin/mg
parente160771f9e318b591a648562d20da0aef2ed39ce (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.h3
-rw-r--r--usr.bin/mg/funmap.c3
-rw-r--r--usr.bin/mg/keymap.c4
-rw-r--r--usr.bin/mg/mg.18
-rw-r--r--usr.bin/mg/word.c162
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.
*/