Mercurial > vim
diff src/ex_docmd.c @ 167:c93c9cad9618
updated for version 7.0051
author | vimboss |
---|---|
date | Tue, 22 Feb 2005 08:39:57 +0000 |
parents | 8b0ee9d57d7f |
children | 8c60f65311fa |
line wrap: on
line diff
--- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -128,6 +128,7 @@ static int getargopt __ARGS((exarg_T *ea static int check_more __ARGS((int, int)); static linenr_T get_address __ARGS((char_u **, int skip, int to_other_file)); +static void get_flags __ARGS((exarg_T *eap)); #if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \ || !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME) static void ex_script_ni __ARGS((exarg_T *eap)); @@ -185,6 +186,7 @@ static void ex_recover __ARGS((exarg_T * static void ex_mode __ARGS((exarg_T *eap)); static void ex_wrongmodifier __ARGS((exarg_T *eap)); static void ex_find __ARGS((exarg_T *eap)); +static void ex_open __ARGS((exarg_T *eap)); static void ex_edit __ARGS((exarg_T *eap)); #if !defined(FEAT_GUI) && !defined(FEAT_CLIENTSERVER) # define ex_drop ex_ni @@ -271,6 +273,7 @@ static void ex_winpos __ARGS((exarg_T *e static void ex_operators __ARGS((exarg_T *eap)); static void ex_put __ARGS((exarg_T *eap)); static void ex_copymove __ARGS((exarg_T *eap)); +static void ex_may_print __ARGS((exarg_T *eap)); static void ex_submagic __ARGS((exarg_T *eap)); static void ex_join __ARGS((exarg_T *eap)); static void ex_at __ARGS((exarg_T *eap)); @@ -570,19 +573,22 @@ do_exmode(improved) int save_msg_scroll; int prev_msg_row; linenr_T prev_line; + int changedtick; + + if (improved) + exmode_active = EXMODE_VIM; + else + exmode_active = EXMODE_NORMAL; + State = NORMAL; + + /* When using ":global /pat/ visual" and then "Q" we return to continue + * the :global command. */ + if (global_busy) + return; save_msg_scroll = msg_scroll; ++RedrawingDisabled; /* don't redisplay the window */ ++no_wait_return; /* don't wait for return */ - if (improved) - exmode_active = EXMODE_VIM; - else - { - settmode(TMODE_COOK); - exmode_active = EXMODE_NORMAL; - } - - State = NORMAL; #ifdef FEAT_GUI /* Ignore scrollbar and mouse events in Ex mode */ ++hold_gui_events; @@ -606,6 +612,7 @@ do_exmode(improved) need_wait_return = FALSE; ex_pressedreturn = FALSE; ex_no_reprint = FALSE; + changedtick = curbuf->b_changedtick; prev_msg_row = msg_row; prev_line = curwin->w_cursor.lnum; #ifdef FEAT_SNIFF @@ -620,29 +627,38 @@ do_exmode(improved) do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT); lines_left = Rows - 1; - if (prev_line != curwin->w_cursor.lnum && !ex_no_reprint) - { - if (ex_pressedreturn) - { - /* go up one line, to overwrite the ":<CR>" line, so the - * output doensn't contain empty lines. */ - msg_row = prev_msg_row; - if (prev_msg_row == Rows - 1) - msg_row--; - } - msg_col = 0; - print_line_no_prefix(curwin->w_cursor.lnum, FALSE); - msg_clr_eos(); - } - else if (ex_pressedreturn) /* must be at EOF */ - EMSG(_("E501: At end-of-file")); + if ((prev_line != curwin->w_cursor.lnum + || changedtick != curbuf->b_changedtick) && !ex_no_reprint) + { + if (curbuf->b_ml.ml_flags & ML_EMPTY) + EMSG(_(e_emptybuf)); + else + { + if (ex_pressedreturn) + { + /* go up one line, to overwrite the ":<CR>" line, so the + * output doensn't contain empty lines. */ + msg_row = prev_msg_row; + if (prev_msg_row == Rows - 1) + msg_row--; + } + msg_col = 0; + print_line_no_prefix(curwin->w_cursor.lnum, FALSE, FALSE); + msg_clr_eos(); + } + } + else if (ex_pressedreturn && !ex_no_reprint) /* must be at EOF */ + { + if (curbuf->b_ml.ml_flags & ML_EMPTY) + EMSG(_(e_emptybuf)); + else + EMSG(_("E501: At end-of-file")); + } } #ifdef FEAT_GUI --hold_gui_events; #endif - if (!improved) - settmode(TMODE_RAW); --RedrawingDisabled; --no_wait_return; update_screen(CLEAR); @@ -1663,7 +1679,8 @@ do_one_cmd(cmdlinep, sourcing, /* in ex mode, an empty line works like :+ */ if (*ea.cmd == NUL && exmode_active && (getline_equal(getline, cookie, getexmodeline) - || getline_equal(getline, cookie, getexline))) + || getline_equal(getline, cookie, getexline)) + && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { ea.cmd = (char_u *)"+"; ex_pressedreturn = TRUE; @@ -1671,7 +1688,10 @@ do_one_cmd(cmdlinep, sourcing, /* ignore comment and empty lines */ if (*ea.cmd == '"' || *ea.cmd == NUL) + { + ex_pressedreturn = TRUE; goto doend; + } /* * 2. handle command modifiers. @@ -1936,7 +1956,7 @@ do_one_cmd(cmdlinep, sourcing, */ if (ea.skip) /* skip this if inside :if */ goto doend; - if (*ea.cmd == '|') + if (*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2)) { ea.cmdidx = CMD_print; ea.argt = RANGE+COUNT+TRLBAR; @@ -1948,14 +1968,12 @@ do_one_cmd(cmdlinep, sourcing, } else if (ea.addr_count != 0) { - if (ea.line2 < 0) - errormsg = invalid_range(&ea); + if (ea.line2 < 0 || ea.line2 > curbuf->b_ml.ml_line_count) + errormsg = (char_u *)_(e_invrange); else { if (ea.line2 == 0) curwin->w_cursor.lnum = 1; - else if (ea.line2 > curbuf->b_ml.ml_line_count) - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; else curwin->w_cursor.lnum = ea.line2; beginline(BL_SOL | BL_FIX); @@ -2090,7 +2108,7 @@ do_one_cmd(cmdlinep, sourcing, */ if (!global_busy && ea.line1 > ea.line2) { - if (sourcing) + if (sourcing || exmode_active) { errormsg = (char_u *)_("E493: Backwards range given"); goto doend; @@ -2280,9 +2298,13 @@ do_one_cmd(cmdlinep, sourcing, /* * Check for <newline> to end a shell command. - * Also do this for ":read !cmd" and ":write !cmd". + * Also do this for ":read !cmd", ":write !cmd" and ":global". + * Any others? */ - else if (ea.cmdidx == CMD_bang || ea.usefilter) + else if (ea.cmdidx == CMD_bang + || ea.cmdidx == CMD_global + || ea.cmdidx == CMD_vglobal + || ea.usefilter) { for (p = ea.arg; *p; ++p) { @@ -2367,6 +2389,12 @@ do_one_cmd(cmdlinep, sourcing, ea.line2 = curbuf->b_ml.ml_line_count; } } + + /* + * Check for flags: 'l', 'p' and '#'. + */ + if (ea.argt & EXFLAGS) + get_flags(&ea); /* no arguments allowed */ if (!ni && !(ea.argt & EXTRA) && *ea.arg != NUL && vim_strchr((char_u *)"|\"", *ea.arg) == NULL) @@ -2661,6 +2689,7 @@ find_command(eap, full) { int len; char_u *p; + int i; /* * Isolate the command and search for it in the command table. @@ -2669,6 +2698,7 @@ find_command(eap, full) * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' * but :sre[wind] is another command, as are :scrip[tnames], * :scs[cope], :sim[alt], :sig[ns] and :sil[ent]. + * - the "d" command can directly be followed by 'l' or 'p' flag. */ p = eap->cmd; if (*p == 'k') @@ -2694,6 +2724,22 @@ find_command(eap, full) if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) ++p; len = (int)(p - eap->cmd); + if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) + { + /* Check for ":dl", ":dell", etc. to ":deletel": that's + * :delete with the 'l' flag. Same for 'p'. */ + for (i = 0; i < len; ++i) + if (eap->cmd[i] != "delete"[i]) + break; + if (i == len - 1) + { + --len; + if (p[-1] == 'l') + eap->flags |= EXFLAG_LIST; + else + eap->flags |= EXFLAG_PRINT; + } + } if (ASCII_ISLOWER(*eap->cmd)) eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)]; @@ -2928,8 +2974,6 @@ set_one_cmd_context(xp, buff) /* * 4. parse command */ - - cmd = skipwhite(cmd); xp->xp_pattern = cmd; if (*cmd == NUL) return NULL; @@ -3281,6 +3325,7 @@ set_one_cmd_context(xp, buff) case CMD_botright: case CMD_browse: case CMD_confirm: + case CMD_debug: case CMD_folddoclosed: case CMD_folddoopen: case CMD_hide: @@ -3633,6 +3678,7 @@ set_one_cmd_context(xp, buff) * Backslashed delimiters after / or ? will be skipped, and commands will * not be expanded between /'s and ?'s or after "'". * + * Also skip white space and ":" characters. * Returns the "cmd" pointer advanced to beyond the range. */ char_u * @@ -3642,8 +3688,7 @@ skip_range(cmd, ctx) { int delim; - while (*cmd != NUL && (vim_isspace(*cmd) || VIM_ISDIGIT(*cmd) || - vim_strchr((char_u *)".$%'/?-+,;", *cmd) != NULL)) + while (vim_strchr((char_u *)" \t0123456789.$%'/?-+,;", *cmd) != NULL) { if (*cmd == '\'') { @@ -3662,6 +3707,11 @@ skip_range(cmd, ctx) if (*cmd != NUL) ++cmd; } + + /* Skip ":" and white space. */ + while (*cmd == ':') + cmd = skipwhite(cmd + 1); + return cmd; } @@ -3856,6 +3906,25 @@ error: } /* + * Get flags from an Ex command argument. + */ + static void +get_flags(eap) + exarg_T *eap; +{ + while (vim_strchr((char_u *)"lp#", *eap->arg) != NULL) + { + if (*eap->arg == 'l') + eap->flags |= EXFLAG_LIST; + else if (*eap->arg == 'p') + eap->flags |= EXFLAG_PRINT; + else + eap->flags |= EXFLAG_NR; + eap->arg = skipwhite(eap->arg + 1); + } +} + +/* * Function called for command which is Not Implemented. NI! */ void @@ -4280,7 +4349,7 @@ separate_nextcmd(eap) #ifdef FEAT_EVAL /* Skip over `=expr` when wildcards are expanded. */ - else if (p[0] == '`' && p[1] == '=') + else if (p[0] == '`' && p[1] == '=' && (eap->argt & XFILE)) { p += 2; (void)skip_expr(&p); @@ -6116,31 +6185,27 @@ ex_exit(eap) ex_print(eap) exarg_T *eap; { - int save_list = 0; /* init for GCC */ - - if (eap->cmdidx == CMD_list) - { - save_list = curwin->w_p_list; - curwin->w_p_list = 1; - } - - for ( ;!got_int; ui_breakcheck()) - { - print_line(eap->line1, - (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound)); - if (++eap->line1 > eap->line2) - break; - out_flush(); /* show one line at a time */ - } - setpcmark(); - /* put cursor at last line */ - curwin->w_cursor.lnum = eap->line2; - beginline(BL_SOL | BL_FIX); + if (curbuf->b_ml.ml_flags & ML_EMPTY) + EMSG(_(e_emptybuf)); + else + { + for ( ;!got_int; ui_breakcheck()) + { + print_line(eap->line1, + (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound + || (eap->flags & EXFLAG_NR)), + eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST)); + if (++eap->line1 > eap->line2) + break; + out_flush(); /* show one line at a time */ + } + setpcmark(); + /* put cursor at last line */ + curwin->w_cursor.lnum = eap->line2; + beginline(BL_SOL | BL_FIX); + } ex_no_reprint = TRUE; - - if (eap->cmdidx == CMD_list) - curwin->w_p_list = save_list; } #ifdef FEAT_BYTEOFF @@ -6689,7 +6754,45 @@ ex_find(eap) } /* - * ":edit", ":badd". + * ":open" simulation: for now just work like ":visual". + */ + static void +ex_open(eap) + exarg_T *eap; +{ + regmatch_T regmatch; + char_u *p; + + curwin->w_cursor.lnum = eap->line2; + beginline(BL_SOL | BL_FIX); + if (*eap->arg == '/') + { + /* ":open /pattern/": put cursor in column found with pattern */ + ++eap->arg; + p = skip_regexp(eap->arg, '/', p_magic, NULL); + *p = NUL; + regmatch.regprog = vim_regcomp(eap->arg, p_magic ? RE_MAGIC : 0); + if (regmatch.regprog != NULL) + { + regmatch.rm_ic = p_ic; + p = ml_get_curline(); + if (vim_regexec(®match, p, (colnr_T)0)) + curwin->w_cursor.col = regmatch.startp[0] - p; + else + EMSG(_(e_nomatch)); + vim_free(regmatch.regprog); + } + /* Move to the NUL, ignore any other arguments. */ + eap->arg += STRLEN(eap->arg); + } + check_cursor(); + + eap->cmdidx = CMD_visual; + do_exedit(eap, NULL); +} + +/* + * ":edit", ":badd", ":visual". */ static void ex_edit(eap) @@ -6711,6 +6814,7 @@ do_exedit(eap, old_curwin) #ifdef FEAT_WINDOWS int need_hide; #endif + int exmode_was = exmode_active; /* * ":vi" command ends Ex mode. @@ -6720,7 +6824,45 @@ do_exedit(eap, old_curwin) { exmode_active = FALSE; if (*eap->arg == NUL) + { + /* Special case: ":global/pat/visual\NLvi-commands" */ + if (global_busy) + { + int rd = RedrawingDisabled; + int nwr = no_wait_return; + int ms = msg_scroll; +#ifdef FEAT_GUI + int he = hold_gui_events; +#endif + + if (eap->nextcmd != NULL) + { + stuffReadbuff(eap->nextcmd); + eap->nextcmd = NULL; + } + + if (exmode_was != EXMODE_VIM) + settmode(TMODE_RAW); + RedrawingDisabled = 0; + no_wait_return = 0; + need_wait_return = FALSE; + msg_scroll = 0; +#ifdef FEAT_GUI + hold_gui_events = 0; +#endif + must_redraw = CLEAR; + + main_loop(FALSE, TRUE); + + RedrawingDisabled = rd; + no_wait_return = nwr; + msg_scroll = ms; +#ifdef FEAT_GUI + hold_gui_events = he; +#endif + } return; + } } if ((eap->cmdidx == CMD_new @@ -6961,7 +7103,9 @@ ex_syncbind(eap) ex_read(eap) exarg_T *eap; { - int i; + int i; + int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + linenr_T lnum; if (eap->usefilter) /* :r!cmd */ do_bang(1, eap, FALSE, FALSE, TRUE); @@ -7011,7 +7155,25 @@ ex_read(eap) EMSG2(_(e_notopen), eap->arg); } else + { + if (empty && exmode_active) + { + /* Delete the empty line that remains. Historically ex does + * this but vi doesn't. */ + if (eap->line2 == 0) + lnum = curbuf->b_ml.ml_line_count; + else + lnum = 1; + if (*ml_get(lnum) == NUL) + { + ml_delete(lnum, FALSE); + deleted_lines_mark(lnum, 1L); + if (curwin->w_cursor.lnum >= lnum) + --curwin->w_cursor.lnum; + } + } redraw_curbuf_later(VALID); + } } } @@ -7034,6 +7196,13 @@ ex_cd(eap) else #endif { + if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() + && !eap->forceit) + { + EMSG(_("E747: Cannot change directory, buffer is modifed (add ! to override)")); + return; + } + /* ":cd -": Change to previous directory */ if (STRCMP(new_dir, "-") == 0) { @@ -7132,6 +7301,7 @@ ex_equal(eap) exarg_T *eap; { smsg((char_u *)"%ld", (long)eap->line2); + ex_may_print(eap); } static void @@ -7361,6 +7531,7 @@ ex_operators(eap) #ifdef FEAT_VIRTUALEDIT virtual_op = MAYBE; #endif + ex_may_print(eap); } /* @@ -7377,7 +7548,8 @@ ex_put(eap) eap->forceit = TRUE; } curwin->w_cursor.lnum = eap->line2; - do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, PUT_LINE); + do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L, + PUT_LINE|PUT_CURSLINE); } /* @@ -7395,6 +7567,7 @@ ex_copymove(eap) eap->nextcmd = NULL; return; } + get_flags(eap); /* * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n' @@ -7414,6 +7587,22 @@ ex_copymove(eap) ex_copy(eap->line1, eap->line2, n); u_clearline(); beginline(BL_SOL | BL_FIX); + ex_may_print(eap); +} + +/* + * Print the current line if flags were given to the Ex command. + */ + static void +ex_may_print(eap) + exarg_T *eap; +{ + if (eap->flags != 0) + { + print_line(curwin->w_cursor.lnum, (eap->flags & EXFLAG_NR), + (eap->flags & EXFLAG_LIST)); + ex_no_reprint = TRUE; + } } /* @@ -7451,6 +7640,7 @@ ex_join(eap) } do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit); beginline(BL_WHITE | BL_FIX); + ex_may_print(eap); } /* @@ -7474,7 +7664,9 @@ ex_at(eap) c = '@'; /* put the register in mapbuf */ if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL) + { beep_flush(); + } else { int save_efr = exec_from_reg; @@ -7602,18 +7794,36 @@ ex_redir(eap) /* make register empty */ write_reg_contents(redir_reg, (char_u *)"", -1, FALSE); } - if (*arg != NUL) - EMSG2(_(e_invarg2), eap->arg); + } + if (*arg != NUL) + { + EMSG2(_(e_invarg2), eap->arg); + redir_reg = 0; + } + } + else if (*arg == '=' && arg[1] == '>') + { + int append; + + /* redirect to a variable */ + close_redir(); + arg += 2; + + if (*arg == '>') + { + ++arg; + append = TRUE; } else - EMSG2(_(e_invarg2), eap->arg); + append = FALSE; + + if (var_redir_start(skipwhite(arg), append) == OK) + redir_vname = 1; } #endif /* TODO: redirect to a buffer */ - /* TODO: redirect to an internal variable */ - else EMSG2(_(e_invarg2), eap->arg); } @@ -7690,6 +7900,11 @@ close_redir() } #ifdef FEAT_EVAL redir_reg = 0; + if (redir_vname) + { + var_redir_stop(); + redir_vname = 0; + } #endif } @@ -7774,8 +7989,7 @@ ex_mkrc(eap) #if defined(FEAT_SESSION) && defined(vim_mkdir) /* When using 'viewdir' may have to create the directory. */ if (using_vdir && !mch_isdir(p_vdir)) - if (vim_mkdir(p_vdir, 0755) != 0) - EMSG2(_("E739: Cannot create directory: %s"), p_vdir); + vim_mkdir_emsg(p_vdir, 0755); #endif fd = open_exfile(fname, eap->forceit, WRITEBIN); @@ -7893,6 +8107,22 @@ theend: #endif } +#if ((defined(FEAT_SESSION) || defined(FEAT_EVAL)) && defined(vim_mkdir)) \ + || defined(PROTO) + int +vim_mkdir_emsg(name, prot) + char_u *name; + int prot; +{ + if (vim_mkdir(name, prot) != 0) + { + EMSG2(_("E739: Cannot create directory: %s"), name); + return FAIL; + } + return OK; +} +#endif + /* * Open a file for writing for an Ex command, with some checks. * Return file descriptor, or NULL on failure.