📄 vcmd.c
字号:
/* vcmd.c *//* Author: * Steve Kirkendall * 14407 SW Teal Blvd. #C * Beaverton, OR 97005 * kirkenda@cs.pdx.edu *//* This file contains the functions that handle VI commands */#include "config.h"#include "ctype.h"#include "vi.h"#if MSDOS# include <process.h># include <string.h>#endif#if TOS# include <osbind.h># include <string.h>#endif#if OSK# include <stdio.h>#endif/* This function puts the editor in EX mode */MARK v_quit(){ move(LINES - 1, 0); mode = MODE_EX; return cursor;}/* This function causes the screen to be redrawn */MARK v_redraw(){ redraw(MARK_UNSET, FALSE); return cursor;}/* This function executes a string of EX commands, and waits for a user keystroke * before returning to the VI screen. If that keystroke is another ':', then * another EX command is read and executed. *//*ARGSUSED*/MARK v_1ex(m, text) MARK m; /* the current line */ char *text; /* the first command to execute */{ /* run the command. be careful about modes & output */ exwrote = (mode == MODE_COLON); doexcmd(text); exrefresh(); /* if mode is no longer MODE_VI, then we should quit right away! */ if (mode != MODE_VI && mode != MODE_COLON) return cursor; /* The command did some output. Wait for a keystoke. */ if (exwrote) { mode = MODE_VI; msg("[Hit <RETURN> to continue]"); if (getkey(0) == ':') { mode = MODE_COLON; addch('\n'); } else redraw(MARK_UNSET, FALSE); } return cursor;}/* This function undoes the last change *//*ARGSUSED*/MARK v_undo(m) MARK m; /* (ignored) */{ if (undo()) { redraw(MARK_UNSET, FALSE); } return cursor;}/* This function deletes the character(s) that the cursor is on */MARK v_xchar(m, cnt, cmd) MARK m; /* where to start deletions */ long cnt; /* number of chars to delete */ int cmd; /* either 'x' or 'X' */{ DEFAULT(1); /* for 'X', adjust so chars are deleted *BEFORE* cursor */ if (cmd == 'X') { if (markidx(m) < cnt) return MARK_UNSET; m -= cnt; } /* make sure we don't try to delete more thars than there are */ pfetch(markline(m)); if (markidx(m + cnt) > plen) { cnt = plen - markidx(m); } if (cnt == 0L) { return MARK_UNSET; } /* do it */ ChangeText { cut(m, m + cnt); delete(m, m + cnt); } return m;}/* This function defines a mark *//*ARGSUSED*/MARK v_mark(m, count, key) MARK m; /* where the mark will be */ long count; /* (ignored) */ int key; /* the ASCII label of the mark */{ if (key < 'a' || key > 'z') { msg("Marks must be from a to z"); } else { mark[key - 'a'] = m; } return m;}/* This function toggles upper & lower case letters */MARK v_ulcase(m, cnt) MARK m; /* where to make the change */ long cnt; /* number of chars to flip */{ REG char *pos; REG int j; DEFAULT(1); /* fetch the current version of the line */ pfetch(markline(m)); /* for each position in the line */ for (j = 0, pos = &ptext[markidx(m)]; j < cnt && *pos; j++, pos++) { if (isupper(*pos)) { tmpblk.c[j] = tolower(*pos); } else { tmpblk.c[j] = toupper(*pos); } } /* if the new text is different from the old, then change it */ if (strncmp(tmpblk.c, &ptext[markidx(m)], j)) { ChangeText { tmpblk.c[j] = '\0'; change(m, m + j, tmpblk.c); } } return m + j;}MARK v_replace(m, cnt, key) MARK m; /* first char to be replaced */ long cnt; /* number of chars to replace */ int key; /* what to replace them with */{ REG char *text; REG int i; DEFAULT(1); /* map ^M to '\n' */ if (key == '\r') { key = '\n'; } /* make sure the resulting line isn't too long */ if (cnt > BLKSIZE - 2 - markidx(m)) { cnt = BLKSIZE - 2 - markidx(m); } /* build a string of the desired character with the desired length */ for (text = tmpblk.c, i = cnt; i > 0; i--) { *text++ = key; } *text = '\0'; /* make sure cnt doesn't extend past EOL */ pfetch(markline(m)); key = markidx(m); if (key + cnt > plen) { cnt = plen - key; } /* do the replacement */ ChangeText { change(m, m + cnt, tmpblk.c); } if (*tmpblk.c == '\n') { return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE; } else { return m + cnt - 1; }}MARK v_overtype(m) MARK m; /* where to start overtyping */{ MARK end; /* end of a substitution */ static long width; /* width of a single-line replace */ /* the "doingdot" version of replace is really a substitution */ if (doingdot) { /* was the last one really repeatable? */ if (width < 0) { msg("Can't repeat a multi-line overtype command"); return MARK_UNSET; } /* replacing nothing by nothing? Don't bother */ if (width == 0) { return m; } /* replace some chars by repeated text */ return v_subst(m, width); } /* Normally, we input starting here, in replace mode */ ChangeText { end = input(m, m, WHEN_VIREP, FALSE); } /* if we ended on the same line we started on, then this * overtype is repeatable via the dot key. */ if (markline(end) == markline(m) && end >= m - 1L) { width = end - m + 1L; } else /* it isn't repeatable */ { width = -1L; } return end;}/* This function selects which cut buffer to use *//*ARGSUSED*/MARK v_selcut(m, cnt, key) MARK m; long cnt; int key;{ cutname(key); return m;}/* This function pastes text from a cut buffer *//*ARGSUSED*/MARK v_paste(m, cnt, cmd) MARK m; /* where to paste the text */ long cnt; /* (ignored) */ int cmd; /* either 'p' or 'P' */{ MARK dest; ChangeText { /* paste the text, and find out where it ends */ dest = paste(m, cmd == 'p', TRUE); /* was that a line-mode paste? */ if (dest && markline(dest) != markline(m)) { /* line-mode pastes leave the cursor at the front * of the first pasted line. */ dest = m; if (cmd == 'p') { dest += BLKSIZE; } force_flags |= FRNT; } } return dest;}/* This function yanks text into a cut buffer */MARK v_yank(m, n) MARK m, n; /* range of text to yank */{ cut(m, n); return m;}/* This function deletes a range of text */MARK v_delete(m, n) MARK m, n; /* range of text to delete */{ /* illegal to try and delete nothing */ if (n <= m) { return MARK_UNSET; } /* Do it */ ChangeText { cut(m, n); delete(m, n); } return m;}/* This starts input mode without deleting anything */MARK v_insert(m, cnt, key) MARK m; /* where to start (sort of) */ long cnt; /* repeat how many times? */ int key; /* what command is this for? {a,A,i,I,o,O} */{ int wasdot; long reps; int above; /* boolean: new line going above old line? */ DEFAULT(1); ChangeText { /* tweak the insertion point, based on command key */ above = FALSE; switch (key) { case 'i': break; case 'a': pfetch(markline(m)); if (plen > 0) { m++; } break; case 'I': m = m_front(m, 1L); break; case 'A': pfetch(markline(m)); m = (m & ~(BLKSIZE - 1)) + plen; break; case 'O': m &= ~(BLKSIZE - 1); add(m, "\n"); above = TRUE; break; case 'o': m = (m & ~(BLKSIZE - 1)) + BLKSIZE; add(m, "\n"); break; } /* insert the same text once or more */ for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE) { m = input(m, m, WHEN_VIINP, above) + 1; } if (markidx(m) > 0) { m--; } doingdot = wasdot; }#ifndef CRUNCH# ifndef NO_EXTENSIONS if (key == 'i' && *o_inputmode && mode == MODE_VI) { msg("Now in command mode! To return to input mode, hit <i>"); }# endif#endif return m;}/* This starts input mode with some text deleted */MARK v_change(m, n) MARK m, n; /* the range of text to change */{ int lnmode; /* is this a line-mode change? */ /* swap them if they're in reverse order */ if (m > n) { MARK tmp; tmp = m; m = n; n = tmp; } /* for line mode, retain the last newline char */ lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n); if (lnmode) { n -= BLKSIZE; pfetch(markline(n)); n = (n & ~(BLKSIZE - 1)) + plen; } ChangeText { cut(m, n); m = input(m, n, WHEN_VIINP, FALSE); } return m;}/* This function replaces a given number of characters with input */MARK v_subst(m, cnt) MARK m; /* where substitutions start */ long cnt; /* number of chars to replace */{ DEFAULT(1); /* make sure we don't try replacing past EOL */ pfetch(markline(m)); if (markidx(m) + cnt > plen) { cnt = plen - markidx(m); } /* Go for it! */ ChangeText { cut(m, m + cnt); m = input(m, m + cnt, WHEN_VIINP, FALSE); } return m;}/* This calls the ex "join" command to join some lines together */MARK v_join(m, cnt)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -