diff options
author | Bram Moolenaar <Bram@vim.org> | 2005-02-22 08:56:13 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2005-02-22 08:56:13 +0000 |
commit | 5313dcb75ac76501f23d21ac94efdbeeabc860bc (patch) | |
tree | b6c5ac114addb67fdee375a0c1baf75e609d4dff /src/ex_cmds.c | |
parent | 26a60b45245080771bc2452b2634cb1f5acd60ed (diff) |
updated for version 7.0051v7.0051
Diffstat (limited to 'src/ex_cmds.c')
-rw-r--r-- | src/ex_cmds.c | 355 |
1 files changed, 252 insertions, 103 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c index d8f9691357..9ebf39cfb5 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -726,13 +726,15 @@ do_bang(addr_count, eap, forceit, do_in, do_out) /* * do_filter: filter lines through a command given by the user * - * We use temp files and the call_shell() routine here. This would normally - * be done using pipes on a UNIX machine, but this is more portable to - * non-unix machines. The call_shell() routine needs to be able + * We mostly use temp files and the call_shell() routine here. This would + * normally be done using pipes on a UNIX machine, but this is more portable + * to non-unix machines. The call_shell() routine needs to be able * to deal with redirection somehow, and should handle things like looking * at the PATH env. variable, and adding reasonable extensions to the * command name given by the user. All reasonable versions of call_shell() * do this. + * Alternatively, if on Unix and redirecting input or output, but not both, + * and the 'shelltemp' option isn't set, use pipes. * We use input redirection if do_in is TRUE. * We use output redirection if do_out is TRUE. */ @@ -752,6 +754,7 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) #ifdef FEAT_AUTOCMD buf_T *old_curbuf = curbuf; #endif + int shell_flags = 0; if (*cmd == NUL) /* no filter command */ return; @@ -772,27 +775,59 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) invalidate_botline(); /* - * 1. Form temp file names - * 2. Write the lines to a temp file - * 3. Run the filter command on the temp file - * 4. Read the output of the command into the buffer - * 5. Delete the original lines to be filtered - * 6. Remove the temp files + * When using temp files: + * 1. * Form temp file names + * 2. * Write the lines to a temp file + * 3. Run the filter command on the temp file + * 4. * Read the output of the command into the buffer + * 5. * Delete the original lines to be filtered + * 6. * Remove the temp files + * + * When writing the input with a pipe or when catching the output with a + * pipe only need to do 3. */ - if ((do_in && (itmp = vim_tempname('i')) == NULL) - || (do_out && (otmp = vim_tempname('o')) == NULL)) + if (do_out) + shell_flags |= SHELL_DOOUT; + +#if !defined(USE_SYSTEM) && defined(UNIX) + if (!do_in && do_out && !p_stmp) { - EMSG(_(e_notmp)); - goto filterend; + /* Use a pipe to fetch stdout of the command, do not use a temp file. */ + shell_flags |= SHELL_READ; + curwin->w_cursor.lnum = line2; + } + else if (do_in && !do_out && !p_stmp) + { + /* Use a pipe to write stdin of the command, do not use a temp file. */ + shell_flags |= SHELL_WRITE; + curbuf->b_op_start.lnum = line1; + curbuf->b_op_end.lnum = line2; + } + else if (do_in && do_out && !p_stmp) + { + /* Use a pipe to write stdin and fetch stdout of the command, do not + * use a temp file. */ + shell_flags |= SHELL_READ|SHELL_WRITE; + curbuf->b_op_start.lnum = line1; + curbuf->b_op_end.lnum = line2; + curwin->w_cursor.lnum = line2; } + else +#endif + if ((do_in && (itmp = vim_tempname('i')) == NULL) + || (do_out && (otmp = vim_tempname('o')) == NULL)) + { + EMSG(_(e_notmp)); + goto filterend; + } /* * The writing and reading of temp files will not be shown. * Vi also doesn't do this and the messages are not very informative. */ ++no_wait_return; /* don't call wait_return() while busy */ - if (do_in && buf_write(curbuf, itmp, NULL, line1, line2, eap, + if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap, FALSE, FALSE, FALSE, TRUE) == FAIL) { msg_putchar('\n'); /* keep message from buf_write() */ @@ -828,6 +863,14 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in) redraw_later_clear(); + if (do_out) + { + if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL) + goto error; + redraw_curbuf_later(VALID); + } + read_linecount = curbuf->b_ml.ml_line_count; + /* * When call_shell() fails wait_return() is called to give the user a * chance to read the error messages. Otherwise errors are ignored, so you @@ -837,8 +880,7 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) * like ":r !cat" hangs. * Pass on the SHELL_DOOUT flag when the output is being redirected. */ - if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED - | (do_out ? SHELL_DOOUT : 0))) + if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED | shell_flags)) { redraw_later_clear(); wait_return(FALSE); @@ -856,32 +898,39 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) if (do_out) { - if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL) - goto error; - redraw_curbuf_later(VALID); - read_linecount = curbuf->b_ml.ml_line_count; - if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap, - READ_FILTER) == FAIL) + if (otmp != NULL) { + if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, + eap, READ_FILTER) == FAIL) + { #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL) - if (!aborting()) + if (!aborting()) #endif - { - msg_putchar('\n'); - EMSG2(_(e_notread), otmp); + { + msg_putchar('\n'); + EMSG2(_(e_notread), otmp); + } + goto error; } - goto error; - } #ifdef FEAT_AUTOCMD - if (curbuf != old_curbuf) - goto filterend; + if (curbuf != old_curbuf) + goto filterend; #endif + } + + read_linecount = curbuf->b_ml.ml_line_count - read_linecount; + + if (shell_flags & SHELL_READ) + { + curbuf->b_op_start.lnum = line2 + 1; + curbuf->b_op_end.lnum = curwin->w_cursor.lnum; + appended_lines_mark(line2, read_linecount); + } if (do_in) { if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL) { - read_linecount = curbuf->b_ml.ml_line_count - read_linecount; if (read_linecount >= linecount) /* move all marks from old lines to new lines */ mark_adjust(line1, line2, linecount, 0L); @@ -914,8 +963,8 @@ do_filter(line1, line2, eap, cmd, do_in, do_out) /* * Put cursor on last new line for ":r !cmd". */ - curwin->w_cursor.lnum = curbuf->b_op_end.lnum; linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1; + curwin->w_cursor.lnum = curbuf->b_op_end.lnum; } beginline(BL_WHITE | BL_FIX); /* cursor on first non-blank */ @@ -1167,9 +1216,13 @@ make_filter_cmd(cmd, itmp, otmp) #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2) /* - * put braces around the command (for concatenated commands) + * Put braces around the command (for concatenated commands) when + * redirecting input and/or output. */ - sprintf((char *)buf, "(%s)", (char *)cmd); + if (itmp != NULL || otmp != NULL) + sprintf((char *)buf, "(%s)", (char *)cmd); + else + STRCPY(buf, cmd); if (itmp != NULL) { STRCAT(buf, " < "); @@ -1958,9 +2011,10 @@ do_fixdel(eap) } void -print_line_no_prefix(lnum, use_number) +print_line_no_prefix(lnum, use_number, list) linenr_T lnum; int use_number; + int list; { char_u numbuf[30]; @@ -1969,28 +2023,31 @@ print_line_no_prefix(lnum, use_number) sprintf((char *)numbuf, "%*ld ", number_width(curwin), (long)lnum); msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */ } - msg_prt_line(ml_get(lnum)); + msg_prt_line(ml_get(lnum), list); } /* * Print a text line. Also in silent mode ("ex -s"). */ void -print_line(lnum, use_number) +print_line(lnum, use_number, list) linenr_T lnum; int use_number; + int list; { int save_silent = silent_mode; - silent_mode = FALSE; msg_start(); - print_line_no_prefix(lnum, use_number); + silent_mode = FALSE; + info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ + print_line_no_prefix(lnum, use_number, list); if (save_silent) { msg_putchar('\n'); cursor_on(); /* msg_start() switches it off */ out_flush(); silent_mode = save_silent; + info_message = FALSE; } } @@ -3240,6 +3297,8 @@ delbuf_msg(name) } #endif +static int append_indent = 0; /* autoindent for first line */ + /* * ":insert" and ":append", also used by ":change" */ @@ -3255,6 +3314,14 @@ ex_append(eap) int vcol; int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + /* the ! flag toggles autoindent */ + if (eap->forceit) + curbuf->b_p_ai = !curbuf->b_p_ai; + + /* First autoindent comes from the line we start on */ + if (eap->cmdidx != CMD_change && curbuf->b_p_ai && lnum > 0) + append_indent = get_indent_lnum(lnum); + if (eap->cmdidx != CMD_append) --lnum; @@ -3270,14 +3337,31 @@ ex_append(eap) { msg_scroll = TRUE; need_wait_return = FALSE; - if (curbuf->b_p_ai && lnum > 0) - indent = get_indent_lnum(lnum); + if (curbuf->b_p_ai) + { + if (append_indent >= 0) + { + indent = append_indent; + append_indent = -1; + } + else if (lnum > 0) + indent = get_indent_lnum(lnum); + } + ex_keep_indent = FALSE; if (eap->getline == NULL) - theline = getcmdline( -#ifdef FEAT_EVAL - eap->cstack->cs_looplevel > 0 ? -1 : -#endif - NUL, 0L, indent); + { + /* No getline() function, use the lines that follow. This ends + * when there is no more. */ + if (eap->nextcmd == NULL || *eap->nextcmd == NUL) + break; + p = vim_strchr(eap->nextcmd, NL); + if (p == NULL) + p = eap->nextcmd + STRLEN(eap->nextcmd); + theline = vim_strnsave(eap->nextcmd, (int)(p - eap->nextcmd)); + if (*p != NUL) + ++p; + eap->nextcmd = p; + } else theline = eap->getline( #ifdef FEAT_EVAL @@ -3288,6 +3372,10 @@ ex_append(eap) if (theline == NULL) break; + /* Using ^ CTRL-D in getexmodeline() makes us repeat the indent. */ + if (ex_keep_indent) + append_indent = indent; + /* Look for the "." after automatic indent. */ vcol = 0; for (p = theline; indent > vcol; ++p) @@ -3306,13 +3394,16 @@ ex_append(eap) break; } + /* don't use autoindent if nothing was typed. */ + if (p[0] == NUL) + theline[0] = NUL; + did_undo = TRUE; ml_append(lnum, theline, (colnr_T)0, FALSE); appended_lines_mark(lnum, 1L); vim_free(theline); ++lnum; - msg_didout = TRUE; /* also scroll for empty line */ if (empty) { @@ -3322,6 +3413,9 @@ ex_append(eap) } State = NORMAL; + if (eap->forceit) + curbuf->b_p_ai = !curbuf->b_p_ai; + /* "start" is set to eap->line2+1 unless that position is invalid (when * eap->line2 pointed to the end of the buffer and nothig was appended) * "end" is set to lnum when something has been appended, otherwise @@ -3354,6 +3448,10 @@ ex_change(eap) && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) return; + /* the ! flag toggles autoindent */ + if (eap->forceit ? !curbuf->b_p_ai : curbuf->b_p_ai) + append_indent = get_indent_lnum(eap->line1); + for (lnum = eap->line2; lnum >= eap->line1; --lnum) { if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to delete */ @@ -3374,7 +3472,6 @@ ex_z(eap) char_u *x; int bigness; char_u *kind; - int numbered = FALSE; int minus = 0; linenr_T start, end, curs, i; int j; @@ -3392,12 +3489,6 @@ ex_z(eap) bigness = 1; x = eap->arg; - if (*x == '#') - { - numbered = TRUE; - ++x; - } - kind = x; if (*kind == '-' || *kind == '+' || *kind == '=' || *kind == '^' || *kind == '.') @@ -3416,6 +3507,8 @@ ex_z(eap) { bigness = atoi((char *)x); p_window = bigness; + if (*kind == '=') + bigness += 2; } } @@ -3454,8 +3547,10 @@ ex_z(eap) default: /* '+' */ start = lnum; if (*kind == '+') - start += bigness * (x - kind - 1); - end = start + bigness; + start += bigness * (x - kind - 1) + 1; + else if (eap->addr_count == 0) + ++start; + end = start + bigness - 1; curs = end; break; } @@ -3479,7 +3574,7 @@ ex_z(eap) msg_putchar('-'); } - print_line(i, numbered); + print_line(i, eap->flags & EXFLAG_NR, eap->flags & EXFLAG_LIST); if (minus && i == lnum) { @@ -3568,6 +3663,8 @@ do_sub(eap) static int do_ask = FALSE; /* ask for confirmation */ static int do_error = TRUE; /* if false, ignore errors */ static int do_print = FALSE; /* print last line with subs. */ + static int do_list = FALSE; /* list last line with subs. */ + static int do_number = FALSE; /* list last line with line nr*/ static int do_ic = 0; /* ignore case flag */ char_u *pat = NULL, *sub = NULL; /* init for GCC */ int delimiter; @@ -3663,8 +3760,22 @@ do_sub(eap) if (!eap->skip) { - vim_free(old_sub); - old_sub = vim_strsave(sub); + /* In POSIX vi ":s/pat/%/" uses the previous subst. string. */ + if (STRCMP(sub, "%") == 0 + && vim_strchr(p_cpo, CPO_SUBPERCENT) != NULL) + { + if (old_sub == NULL) /* there is no previous command */ + { + EMSG(_(e_nopresub)); + return; + } + sub = old_sub; + } + else + { + vim_free(old_sub); + old_sub = vim_strsave(sub); + } } } else if (!eap->skip) /* use previous pattern and substitution */ @@ -3717,6 +3828,16 @@ do_sub(eap) which_pat = RE_LAST; else if (*cmd == 'p') do_print = TRUE; + else if (*cmd == '#') + { + do_print = TRUE; + do_number = TRUE; + } + else if (*cmd == 'l') + { + do_print = TRUE; + do_list = TRUE; + } else if (*cmd == 'i') /* ignore case */ do_ic = 'i'; else if (*cmd == 'I') /* don't ignore case */ @@ -3932,58 +4053,86 @@ do_sub(eap) */ while (do_ask) { + if (exmode_active) + { + char_u *resp; + colnr_T sc, ec; + + print_line_no_prefix(lnum, FALSE, FALSE); + + getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL); + curwin->w_cursor.col = regmatch.endpos[0].col - 1; + getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec); + msg_start(); + for (i = 0; i < sc; ++i) + msg_putchar(' '); + for ( ; i <= ec; ++i) + msg_putchar('^'); + + resp = getexmodeline('?', NULL, 0); + if (resp != NULL) + { + i = *resp; + vim_free(resp); + } + } + else + { #ifdef FEAT_FOLDING - int save_p_fen = curwin->w_p_fen; + int save_p_fen = curwin->w_p_fen; - curwin->w_p_fen = FALSE; + curwin->w_p_fen = FALSE; #endif - /* Invert the matched string. - * Remove the inversion afterwards. */ - temp = RedrawingDisabled; - RedrawingDisabled = 0; + /* Invert the matched string. + * Remove the inversion afterwards. */ + temp = RedrawingDisabled; + RedrawingDisabled = 0; - search_match_lines = regmatch.endpos[0].lnum; - search_match_endcol = regmatch.endpos[0].col; - highlight_match = TRUE; + search_match_lines = regmatch.endpos[0].lnum; + search_match_endcol = regmatch.endpos[0].col; + highlight_match = TRUE; - update_topline(); - validate_cursor(); - update_screen(NOT_VALID); - highlight_match = FALSE; - redraw_later(NOT_VALID); + update_topline(); + validate_cursor(); + update_screen(NOT_VALID); + highlight_match = FALSE; + redraw_later(NOT_VALID); #ifdef FEAT_FOLDING - curwin->w_p_fen = save_p_fen; -#endif - if (msg_row == Rows - 1) - msg_didout = FALSE; /* avoid a scroll-up */ - msg_starthere(); - i = msg_scroll; - msg_scroll = 0; /* truncate msg when needed */ - msg_no_more = TRUE; - /* write message same highlighting as for wait_return */ - smsg_attr(hl_attr(HLF_R), - (char_u *)_("replace with %s (y/n/a/q/l/^E/^Y)?"), - sub); - msg_no_more = FALSE; - msg_scroll = i; - showruler(TRUE); - windgoto(msg_row, msg_col); - RedrawingDisabled = temp; + curwin->w_p_fen = save_p_fen; +#endif + if (msg_row == Rows - 1) + msg_didout = FALSE; /* avoid a scroll-up */ + msg_starthere(); + i = msg_scroll; + msg_scroll = 0; /* truncate msg when + needed */ + msg_no_more = TRUE; + /* write message same highlighting as for + * wait_return */ + smsg_attr(hl_attr(HLF_R), + (char_u *)_("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); + msg_no_more = FALSE; + msg_scroll = i; + showruler(TRUE); + windgoto(msg_row, msg_col); + RedrawingDisabled = temp; #ifdef USE_ON_FLY_SCROLL - dont_scroll = FALSE; /* allow scrolling here */ -#endif - ++no_mapping; /* don't map this key */ - ++allow_keys; /* allow special keys */ - i = safe_vgetc(); - --allow_keys; - --no_mapping; - - /* clear the question */ - msg_didout = FALSE; /* don't scroll up */ - msg_col = 0; - gotocmdline(TRUE); + dont_scroll = FALSE; /* allow scrolling here */ +#endif + ++no_mapping; /* don't map this key */ + ++allow_keys; /* allow special keys */ + i = safe_vgetc(); + --allow_keys; + --no_mapping; + + /* clear the question */ + msg_didout = FALSE; /* don't scroll up */ + msg_col = 0; + gotocmdline(TRUE); + } + need_wait_return = FALSE; /* no hit-return prompt */ if (i == 'q' || i == ESC || i == Ctrl_C #ifdef UNIX @@ -4328,7 +4477,7 @@ outofmem: else global_need_beginline = TRUE; if (do_print) - print_line(curwin->w_cursor.lnum, FALSE); + print_line(curwin->w_cursor.lnum, do_number, do_list); } else if (!global_busy) { |