From 46c00a6565b8f1f4b7b1041d03eaceaf6ffc4aee Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 14:11:42 +0200 Subject: [PATCH 01/18] patch 7.4.1666 Problem: When reading JSON from a channel all readahead is used. Solution: Use the fill function to reduce overhead. --- src/channel.c | 94 +++++++++++++++++++++++++++++++++++++++------------ src/json.c | 4 ++- src/structs.h | 1 + src/version.c | 2 ++ 4 files changed, 78 insertions(+), 23 deletions(-) diff --git a/src/channel.c b/src/channel.c index ccab2cb447..a506598d7d 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1184,7 +1184,6 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel) int len = (int)STRLEN(line); char_u *p; - /* TODO: check if channel can be written to, do not block on write */ if ((p = alloc(len + 2)) == NULL) return; STRCPY(p, line); @@ -1213,13 +1212,14 @@ channel_write_in(channel_T *channel) in_part->ch_buffer = NULL; return; } - if (in_part->ch_fd == INVALID_FD) - /* pipe was closed */ - return; for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot && lnum <= buf->b_ml.ml_line_count; ++lnum) { + if (in_part->ch_fd == INVALID_FD) + /* pipe was closed */ + return; + /* TODO: check if channel can be written to, do not block on write */ write_buf_line(buf, lnum, channel); ++written; } @@ -1365,10 +1365,12 @@ channel_collapse(channel_T *channel, int part) /* * Store "buf[len]" on "channel"/"part". + * When "prepend" is TRUE put in front, otherwise append at the end. * Returns OK or FAIL. */ static int -channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead) +channel_save(channel_T *channel, int part, char_u *buf, int len, + int prepend, char *lead) { readq_T *node; readq_T *head = &channel->ch_part[part].ch_head; @@ -1400,14 +1402,28 @@ channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead) node->rq_buffer[len] = NUL; } - /* append node to the tail of the queue */ - node->rq_next = NULL; - node->rq_prev = head->rq_prev; - if (head->rq_prev == NULL) + if (prepend) + { + /* preend node to the head of the queue */ + node->rq_next = head->rq_next; + node->rq_prev = NULL; + if (head->rq_next == NULL) + head->rq_prev = node; + else + head->rq_next->rq_prev = node; head->rq_next = node; + } else - head->rq_prev->rq_next = node; - head->rq_prev = node; + { + /* append node to the tail of the queue */ + node->rq_next = NULL; + node->rq_prev = head->rq_prev; + if (head->rq_prev == NULL) + head->rq_next = node; + else + head->rq_prev->rq_next = node; + head->rq_prev = node; + } if (log_fd != NULL && lead != NULL) { @@ -1420,6 +1436,42 @@ channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead) return OK; } + static int +channel_fill(js_read_T *reader) +{ + channel_T *channel = (channel_T *)reader->js_cookie; + int part = reader->js_cookie_arg; + char_u *next = channel_get(channel, part); + int unused; + int len; + char_u *p; + + if (next == NULL) + return FALSE; + + unused = reader->js_end - reader->js_buf - reader->js_used; + if (unused > 0) + { + /* Prepend unused text. */ + len = (int)STRLEN(next); + p = alloc(unused + len + 1); + if (p == NULL) + { + vim_free(next); + return FALSE; + } + mch_memmove(p, reader->js_buf + reader->js_used, unused); + mch_memmove(p + unused, next, len + 1); + vim_free(next); + next = p; + } + + vim_free(reader->js_buf); + reader->js_buf = next; + reader->js_used = 0; + return TRUE; +} + /* * Use the read buffer of "channel"/"part" and parse a JSON message that is * complete. The messages are added to the queue. @@ -1439,19 +1491,17 @@ channel_parse_json(channel_T *channel, int part) if (channel_peek(channel, part) == NULL) return FALSE; - /* TODO: make reader work properly */ - /* reader.js_buf = channel_peek(channel, part); */ - reader.js_buf = channel_get_all(channel, part); + reader.js_buf = channel_get(channel, part); reader.js_used = 0; - reader.js_fill = NULL; - /* reader.js_fill = channel_fill; */ + reader.js_fill = channel_fill; reader.js_cookie = channel; + reader.js_cookie_arg = part; /* When a message is incomplete we wait for a short while for more to * arrive. After the delay drop the input, otherwise a truncated string * or list will make us hang. */ status = json_decode(&reader, &listtv, - chanpart->ch_mode == MODE_JS ? JSON_JS : 0); + chanpart->ch_mode == MODE_JS ? JSON_JS : 0); if (status == OK) { /* Only accept the response when it is a list with at least two @@ -1552,10 +1602,10 @@ channel_parse_json(channel_T *channel, int part) } else if (reader.js_buf[reader.js_used] != NUL) { - /* Put the unread part back into the channel. - * TODO: insert in front */ + /* Put the unread part back into the channel. */ channel_save(channel, part, reader.js_buf + reader.js_used, - (int)(reader.js_end - reader.js_buf) - reader.js_used, NULL); + (int)(reader.js_end - reader.js_buf) - reader.js_used, + TRUE, NULL); ret = status == MAYBE ? FALSE: TRUE; } else @@ -2419,7 +2469,7 @@ channel_read(channel_T *channel, int part, char *func) break; /* error or nothing more to read */ /* Store the read message in the queue. */ - channel_save(channel, part, buf, len, "RECV "); + channel_save(channel, part, buf, len, FALSE, "RECV "); readlen += len; if (len < MAXMSGSIZE) break; /* did read everything that's available */ @@ -2446,7 +2496,7 @@ channel_read(channel_T *channel, int part, char *func) if (channel->ch_part[part].ch_mode == MODE_RAW || channel->ch_part[part].ch_mode == MODE_NL) channel_save(channel, part, (char_u *)DETACH_MSG_RAW, - (int)STRLEN(DETACH_MSG_RAW), "PUT "); + (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT "); /* TODO: When reading from stdout is not possible, should we try to * keep stdin and stderr open? Probably not, assume the other side diff --git a/src/json.c b/src/json.c index 9738fc5fec..b4ebe74146 100644 --- a/src/json.c +++ b/src/json.c @@ -350,8 +350,10 @@ json_skip_white(js_read_T *reader) if (reader->js_fill != NULL && c == NUL) { if (reader->js_fill(reader)) + { reader->js_end = reader->js_buf + STRLEN(reader->js_buf); - continue; + continue; + } } if (c == NUL || c > ' ') break; diff --git a/src/structs.h b/src/structs.h index abfe6cd781..68b791789e 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2971,6 +2971,7 @@ struct js_reader /* function to fill the buffer or NULL; * return TRUE when the buffer was filled */ void *js_cookie; /* can be used by js_fill */ + int js_cookie_arg; /* can be used by js_fill */ }; typedef struct js_reader js_read_T; diff --git a/src/version.c b/src/version.c index e183717f4d..5a55707fa3 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1666, /**/ 1665, /**/ From 84e1d2b21a424f2687b61daaf84f5fc4f1ab0abe Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 14:20:41 +0200 Subject: [PATCH 02/18] patch 7.4.1667 Problem: Win32: waiting on a pipe with fixed sleep time. Solution: Start with a short delay and increase it when looping. --- src/channel.c | 18 ++++++++++++------ src/version.c | 2 ++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/channel.c b/src/channel.c index a506598d7d..70c4413535 100644 --- a/src/channel.c +++ b/src/channel.c @@ -2371,8 +2371,9 @@ channel_wait(channel_T *channel, sock_T fd, int timeout) if (fd != channel->CH_SOCK_FD) { DWORD nread; - int diff; + int sleep_time; DWORD deadline = GetTickCount() + timeout; + int delay = 1; /* reading from a pipe, not a socket */ while (TRUE) @@ -2380,12 +2381,17 @@ channel_wait(channel_T *channel, sock_T fd, int timeout) if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) && nread > 0) return OK; - diff = deadline - GetTickCount(); - if (diff <= 0) + sleep_time = deadline - GetTickCount(); + if (sleep_time <= 0) break; - /* Wait for 5 msec. - * TODO: increase the sleep time when looping more often */ - Sleep(5); + /* Wait for a little while. Very short at first, up to 10 msec + * after looping a few times. */ + if (sleep_time > delay) + sleep_time = delay; + Sleep(sleep_time); + delay = delay * 2; + if (delay > 10) + delay = 10; } } else diff --git a/src/version.c b/src/version.c index 5a55707fa3..ae5d4b021f 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1667, /**/ 1666, /**/ From ee1f7b3cb71684aaa9bf457e2caf9d02187e6b7c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 14:42:14 +0200 Subject: [PATCH 03/18] patch 7.4.1668 Problem: channel_get_all() does multiple allocations. Solution: Compute the size and allocate once. --- src/channel.c | 39 ++++++++++++++++++++++++++++++--------- src/version.c | 2 ++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/channel.c b/src/channel.c index 70c4413535..c9c0b7c95b 100644 --- a/src/channel.c +++ b/src/channel.c @@ -434,7 +434,6 @@ channel_read_fd(int fd) /* * Read a command from netbeans. - * TODO: instead of channel ID use the FD. */ #ifdef FEAT_GUI_X11 static void @@ -1325,11 +1324,34 @@ channel_get(channel_T *channel, int part) static char_u * channel_get_all(channel_T *channel, int part) { - /* Concatenate everything into one buffer. - * TODO: avoid multiple allocations. */ - while (channel_collapse(channel, part) == OK) - ; - return channel_get(channel, part); + readq_T *head = &channel->ch_part[part].ch_head; + readq_T *node = head->rq_next; + long_u len = 1; + char_u *res; + char_u *p; + + /* If there is only one buffer just get that one. */ + if (head->rq_next == NULL || head->rq_next->rq_next == NULL) + return channel_get(channel, part); + + /* Concatenate everything into one buffer. */ + for (node = head->rq_next; node != NULL; node = node->rq_next) + len += (long_u)STRLEN(node->rq_buffer); + res = lalloc(len, TRUE); + if (res == NULL) + return NULL; + *res = NUL; + for (node = head->rq_next; node != NULL; node = node->rq_next) + STRCAT(res, node->rq_buffer); + + /* Free all buffers */ + do + { + p = channel_get(channel, part); + vim_free(p); + } while (p != NULL); + + return res; } /* @@ -2504,9 +2526,8 @@ channel_read(channel_T *channel, int part, char *func) channel_save(channel, part, (char_u *)DETACH_MSG_RAW, (int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT "); - /* TODO: When reading from stdout is not possible, should we try to - * keep stdin and stderr open? Probably not, assume the other side - * has died. */ + /* When reading from stdout is not possible, assume the other side has + * died. */ channel_close(channel, TRUE); if (channel->ch_nb_close_cb != NULL) (*channel->ch_nb_close_cb)(); diff --git a/src/version.c b/src/version.c index ae5d4b021f..9ba137583e 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1668, /**/ 1667, /**/ From 8b877ac38e96424a08a8b8eb713ef4b3cf0064be Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 19:16:20 +0200 Subject: [PATCH 04/18] patch 7.4.1669 Problem: When writing buffer lines to a pipe Vim may block. Solution: Avoid blocking, write more lines later. --- src/channel.c | 293 +++++++++++++++++++++++++++++++---- src/misc2.c | 3 + src/os_unix.c | 12 +- src/proto/channel.pro | 6 +- src/structs.h | 7 +- src/testdir/test_channel.vim | 8 +- src/version.c | 2 + src/vim.h | 2 - 8 files changed, 288 insertions(+), 45 deletions(-) diff --git a/src/channel.c b/src/channel.c index c9c0b7c95b..ba9f9c736c 100644 --- a/src/channel.c +++ b/src/channel.c @@ -973,6 +973,7 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options) /* Special mode: send last-but-one line when appending a line * to the buffer. */ in_part->ch_buffer->b_write_to_channel = TRUE; + in_part->ch_buf_append = TRUE; in_part->ch_buf_top = in_part->ch_buffer->b_ml.ml_line_count + 1; } @@ -1047,6 +1048,8 @@ channel_set_options(channel_T *channel, jobopt_T *opt) channel->ch_part[PART_OUT].ch_timeout = opt->jo_out_timeout; if (opt->jo_set & JO_ERR_TIMEOUT) channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout; + if (opt->jo_set & JO_BLOCK_WRITE) + channel->ch_part[PART_IN].ch_block_write = 1; if (opt->jo_set & JO_CALLBACK) { @@ -1192,10 +1195,79 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel) vim_free(p); } +/* + * Return TRUE if "channel" can be written to. + * Returns FALSE if the input is closed or the write would block. + */ + static int +can_write_buf_line(channel_T *channel) +{ + chanpart_T *in_part = &channel->ch_part[PART_IN]; + + if (in_part->ch_fd == INVALID_FD) + return FALSE; /* pipe was closed */ + + /* for testing: block every other attempt to write */ + if (in_part->ch_block_write == 1) + in_part->ch_block_write = -1; + else if (in_part->ch_block_write == -1) + in_part->ch_block_write = 1; + + /* TODO: Win32 implementation, probably using WaitForMultipleObjects() */ +#ifndef WIN32 + { +# if defined(HAVE_SELECT) + struct timeval tval; + fd_set wfds; + int ret; + + FD_ZERO(&wfds); + FD_SET((int)in_part->ch_fd, &wfds); + tval.tv_sec = 0; + tval.tv_usec = 0; + for (;;) + { + ret = select((int)in_part->ch_fd + 1, NULL, &wfds, NULL, &tval); +# ifdef EINTR + SOCK_ERRNO; + if (ret == -1 && errno == EINTR) + continue; +# endif + if (ret <= 0 || in_part->ch_block_write == 1) + { + if (ret > 0) + ch_log(channel, "FAKED Input not ready for writing"); + else + ch_log(channel, "Input not ready for writing"); + return FALSE; + } + break; + } +# else + struct pollfd fds; + + fds.fd = in_part->ch_fd; + fds.events = POLLOUT; + if (poll(&fds, 1, 0) <= 0) + { + ch_log(channel, "Input not ready for writing"); + return FALSE; + } + if (in_part->ch_block_write == 1) + { + ch_log(channel, "FAKED Input not ready for writing"); + return FALSE; + } +# endif + } +#endif + return TRUE; +} + /* * Write any lines to the input channel. */ - void + static void channel_write_in(channel_T *channel) { chanpart_T *in_part = &channel->ch_part[PART_IN]; @@ -1203,8 +1275,8 @@ channel_write_in(channel_T *channel) buf_T *buf = in_part->ch_buffer; int written = 0; - if (buf == NULL) - return; + if (buf == NULL || in_part->ch_buf_append) + return; /* no buffer or using appending */ if (!buf_valid(buf) || buf->b_ml.ml_mfp == NULL) { /* buffer was wiped out or unloaded */ @@ -1215,10 +1287,8 @@ channel_write_in(channel_T *channel) for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot && lnum <= buf->b_ml.ml_line_count; ++lnum) { - if (in_part->ch_fd == INVALID_FD) - /* pipe was closed */ - return; - /* TODO: check if channel can be written to, do not block on write */ + if (!can_write_buf_line(channel)) + break; write_buf_line(buf, lnum, channel); ++written; } @@ -1229,6 +1299,37 @@ channel_write_in(channel_T *channel) ch_logn(channel, "written %d lines to channel", written); in_part->ch_buf_top = lnum; + if (lnum > buf->b_ml.ml_line_count) + { + /* Writing is done, no longer need the buffer. */ + in_part->ch_buffer = NULL; + ch_log(channel, "Finished writing all lines to channel"); + } + else + ch_logn(channel, "Still %d more lines to write", + buf->b_ml.ml_line_count - lnum + 1); +} + +/* + * Write any lines waiting to be written to a channel. + */ + void +channel_write_any_lines() +{ + channel_T *channel; + + for (channel = first_channel; channel != NULL; channel = channel->ch_next) + { + chanpart_T *in_part = &channel->ch_part[PART_IN]; + + if (in_part->ch_buffer != NULL) + { + if (in_part->ch_buf_append) + channel_write_new_lines(in_part->ch_buffer); + else + channel_write_in(channel); + } + } } /* @@ -1248,15 +1349,16 @@ channel_write_new_lines(buf_T *buf) linenr_T lnum; int written = 0; - if (in_part->ch_buffer == buf) + if (in_part->ch_buffer == buf && in_part->ch_buf_append) { if (in_part->ch_fd == INVALID_FD) - /* pipe was closed */ - continue; + continue; /* pipe was closed */ found_one = TRUE; for (lnum = in_part->ch_buf_bot; lnum < buf->b_ml.ml_line_count; ++lnum) { + if (!can_write_buf_line(channel)) + break; write_buf_line(buf, lnum, channel); ++written; } @@ -1265,6 +1367,9 @@ channel_write_new_lines(buf_T *buf) ch_logn(channel, "written line %d to channel", (int)lnum - 1); else if (written > 1) ch_logn(channel, "written %d lines to channel", written); + if (lnum < buf->b_ml.ml_line_count) + ch_logn(channel, "Still %d more lines to write", + buf->b_ml.ml_line_count - lnum); in_part->ch_buf_bot = lnum; } @@ -2379,6 +2484,57 @@ channel_free_all(void) /* Buffer size for reading incoming messages. */ #define MAXMSGSIZE 4096 +#if defined(HAVE_SELECT) +/* + * Add write fds where we are waiting for writing to be possible. + */ + static int +channel_fill_wfds(int maxfd_arg, fd_set *wfds) +{ + int maxfd = maxfd_arg; + channel_T *ch; + + for (ch = first_channel; ch != NULL; ch = ch->ch_next) + { + chanpart_T *in_part = &ch->ch_part[PART_IN]; + + if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) + { + FD_SET((int)in_part->ch_fd, wfds); + if ((int)in_part->ch_fd >= maxfd) + maxfd = (int)in_part->ch_fd + 1; + } + } + return maxfd; +} +#else +/* + * Add write fds where we are waiting for writing to be possible. + */ + static int +channel_fill_poll_write(int nfd_in, struct pollfd *fds) +{ + int nfd = nfd_in; + channel_T *ch; + + for (ch = first_channel; ch != NULL; ch = ch->ch_next) + { + chanpart_T *in_part = &ch->ch_part[PART_IN]; + + if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) + { + in_part->ch_poll_idx = nfd; + fds[nfd].fd = in_part->ch_fd; + fds[nfd].events = POLLOUT; + ++nfd; + } + else + in_part->ch_poll_idx = -1; + } + return nfd; +} +#endif + /* * Check for reading from "fd" with "timeout" msec. * Return FAIL when there is nothing to read. @@ -2403,6 +2559,10 @@ channel_wait(channel_T *channel, sock_T fd, int timeout) if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) && nread > 0) return OK; + + /* perhaps write some buffer lines */ + channel_write_any_lines(); + sleep_time = deadline - GetTickCount(); if (sleep_time <= 0) break; @@ -2422,31 +2582,56 @@ channel_wait(channel_T *channel, sock_T fd, int timeout) #if defined(HAVE_SELECT) struct timeval tval; fd_set rfds; - int ret; + fd_set wfds; + int ret; + int maxfd; - FD_ZERO(&rfds); - FD_SET((int)fd, &rfds); tval.tv_sec = timeout / 1000; tval.tv_usec = (timeout % 1000) * 1000; for (;;) { - ret = select((int)fd + 1, &rfds, NULL, NULL, &tval); + FD_ZERO(&rfds); + FD_SET((int)fd, &rfds); + + /* Write lines to a pipe when a pipe can be written to. Need to + * set this every time, some buffers may be done. */ + maxfd = (int)fd + 1; + FD_ZERO(&wfds); + maxfd = channel_fill_wfds(maxfd, &wfds); + + ret = select(maxfd, &rfds, &wfds, NULL, &tval); # ifdef EINTR SOCK_ERRNO; if (ret == -1 && errno == EINTR) continue; # endif if (ret > 0) - return OK; + { + if (FD_ISSET(fd, &rfds)) + return OK; + channel_write_any_lines(); + continue; + } break; } #else - struct pollfd fds; + for (;;) + { + struct pollfd fds[MAX_OPEN_CHANNELS + 1]; + int nfd = 1; - fds.fd = fd; - fds.events = POLLIN; - if (poll(&fds, 1, timeout) > 0) - return OK; + fds[0].fd = fd; + fds[0].events = POLLIN; + nfd = channel_fill_poll_write(nfd, fds); + if (poll(fds, nfd, timeout) > 0) + { + if (fds[0].revents & POLLIN) + return OK; + channel_write_any_lines(); + continue; + } + break; + } #endif } return FAIL; @@ -3010,10 +3195,12 @@ channel_poll_setup(int nfd_in, void *fds_in) { for (part = PART_SOCK; part < PART_IN; ++part) { - if (channel->ch_part[part].ch_fd != INVALID_FD) + chanpart_T *ch_part = &channel->ch_part[part]; + + if (ch_part->ch_fd != INVALID_FD) { - channel->ch_part[part].ch_poll_idx = nfd; - fds[nfd].fd = channel->ch_part[part].ch_fd; + ch_part->ch_poll_idx = nfd; + fds[nfd].fd = ch_part->ch_fd; fds[nfd].events = POLLIN; nfd++; } @@ -3022,6 +3209,8 @@ channel_poll_setup(int nfd_in, void *fds_in) } } + nfd = channel_fill_poll_write(nfd, fds); + return nfd; } @@ -3035,19 +3224,35 @@ channel_poll_check(int ret_in, void *fds_in) channel_T *channel; struct pollfd *fds = fds_in; int part; + int idx; + chanpart_T *in_part; for (channel = first_channel; channel != NULL; channel = channel->ch_next) { for (part = PART_SOCK; part < PART_IN; ++part) { - int idx = channel->ch_part[part].ch_poll_idx; + idx = channel->ch_part[part].ch_poll_idx; - if (ret > 0 && idx != -1 && fds[idx].revents & POLLIN) + if (ret > 0 && idx != -1 && (fds[idx].revents & POLLIN)) { channel_read(channel, part, "channel_poll_check"); --ret; } } + + in_part = &channel->ch_part[PART_IN]; + idx = in_part->ch_poll_idx; + if (ret > 0 && idx != -1 && (fds[idx].revents & POLLOUT)) + { + if (in_part->ch_buf_append) + { + if (in_part->ch_buffer != NULL) + channel_write_new_lines(in_part->ch_buffer); + } + else + channel_write_in(channel); + --ret; + } } return ret; @@ -3056,14 +3261,15 @@ channel_poll_check(int ret_in, void *fds_in) # if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO) /* - * The type of "rfds" is hidden to avoid problems with the function proto. + * The "fd_set" type is hidden to avoid problems with the function proto. */ int -channel_select_setup(int maxfd_in, void *rfds_in) +channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in) { int maxfd = maxfd_in; channel_T *channel; fd_set *rfds = rfds_in; + fd_set *wfds = wfds_in; int part; for (channel = first_channel; channel != NULL; channel = channel->ch_next) @@ -3081,19 +3287,23 @@ channel_select_setup(int maxfd_in, void *rfds_in) } } + maxfd = channel_fill_wfds(maxfd, wfds); + return maxfd; } /* - * The type of "rfds" is hidden to avoid problems with the function proto. + * The "fd_set" type is hidden to avoid problems with the function proto. */ int -channel_select_check(int ret_in, void *rfds_in) +channel_select_check(int ret_in, void *rfds_in, void *wfds_in) { int ret = ret_in; channel_T *channel; fd_set *rfds = rfds_in; + fd_set *wfds = wfds_in; int part; + chanpart_T *in_part; for (channel = first_channel; channel != NULL; channel = channel->ch_next) { @@ -3107,6 +3317,20 @@ channel_select_check(int ret_in, void *rfds_in) --ret; } } + + in_part = &channel->ch_part[PART_IN]; + if (ret > 0 && in_part->ch_fd != INVALID_FD + && FD_ISSET(in_part->ch_fd, wfds)) + { + if (in_part->ch_buf_append) + { + if (in_part->ch_buffer != NULL) + channel_write_new_lines(in_part->ch_buffer); + } + else + channel_write_in(channel); + --ret; + } } return ret; @@ -3608,6 +3832,13 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported) return FAIL; } } + else if (STRCMP(hi->hi_key, "block_write") == 0) + { + if (!(supported & JO_BLOCK_WRITE)) + break; + opt->jo_set |= JO_BLOCK_WRITE; + opt->jo_block_write = get_tv_number(item); + } else break; --todo; @@ -3827,8 +4058,8 @@ job_start(typval_T *argvars) clear_job_options(&opt); opt.jo_mode = MODE_NL; if (get_job_options(&argvars[1], &opt, - JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL - + JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL) + JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT + + JO_EXIT_CB + JO_OUT_IO + JO_BLOCK_WRITE) == FAIL) return job; /* Check that when io is "file" that there is a file name. */ diff --git a/src/misc2.c b/src/misc2.c index ca340b71e5..a0cce07f66 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -6230,6 +6230,9 @@ parse_queued_messages(void) netbeans_parse_messages(); # endif # ifdef FEAT_JOB_CHANNEL + /* Write any buffer lines still to be written. */ + channel_write_any_lines(); + /* Process the messages queued on channels. */ channel_parse_messages(); # endif diff --git a/src/os_unix.c b/src/os_unix.c index 74ffe93001..dc8e00952a 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5539,7 +5539,8 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop) # endif #endif #ifndef HAVE_SELECT - struct pollfd fds[6 + MAX_OPEN_CHANNELS]; + /* each channel may use in, out and err */ + struct pollfd fds[6 + 3 * MAX_OPEN_CHANNELS]; int nfd; # ifdef FEAT_XCLIPBOARD int xterm_idx = -1; @@ -5652,7 +5653,7 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop) struct timeval tv; struct timeval *tvp; - fd_set rfds, efds; + fd_set rfds, wfds, efds; int maxfd; long towait = msec; @@ -5685,6 +5686,7 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop) */ select_eintr: FD_ZERO(&rfds); + FD_ZERO(&wfds); FD_ZERO(&efds); FD_SET(fd, &rfds); # if !defined(__QNX__) && !defined(__CYGWIN32__) @@ -5725,10 +5727,10 @@ select_eintr: } # endif # ifdef FEAT_JOB_CHANNEL - maxfd = channel_select_setup(maxfd, &rfds); + maxfd = channel_select_setup(maxfd, &rfds, &wfds); # endif - ret = select(maxfd + 1, &rfds, NULL, &efds, tvp); + ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp); result = ret > 0 && FD_ISSET(fd, &rfds); if (result) --ret; @@ -5810,7 +5812,7 @@ select_eintr: # endif #ifdef FEAT_JOB_CHANNEL if (ret > 0) - ret = channel_select_check(ret, &rfds); + ret = channel_select_check(ret, &rfds, &wfds); #endif #endif /* HAVE_SELECT */ diff --git a/src/proto/channel.pro b/src/proto/channel.pro index e334908756..b796d82bfe 100644 --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -13,7 +13,7 @@ void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err); void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options); void channel_set_options(channel_T *channel, jobopt_T *opt); void channel_set_req_callback(channel_T *channel, int part, char_u *callback, partial_T *partial, int id); -void channel_write_in(channel_T *channel); +void channel_write_any_lines(void); void channel_write_new_lines(buf_T *buf); char_u *channel_get(channel_T *channel, int part); int channel_collapse(channel_T *channel, int part); @@ -37,8 +37,8 @@ void ch_expr_common(typval_T *argvars, typval_T *rettv, int eval); void ch_raw_common(typval_T *argvars, typval_T *rettv, int eval); int channel_poll_setup(int nfd_in, void *fds_in); int channel_poll_check(int ret_in, void *fds_in); -int channel_select_setup(int maxfd_in, void *rfds_in); -int channel_select_check(int ret_in, void *rfds_in); +int channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in); +int channel_select_check(int ret_in, void *rfds_in, void *wfds_in); int channel_parse_messages(void); int set_ref_in_channel(int copyID); int channel_part_send(channel_T *channel); diff --git a/src/structs.h b/src/structs.h index 68b791789e..e753860b82 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1383,12 +1383,15 @@ typedef struct { #else struct timeval ch_deadline; #endif + int ch_block_write; /* for testing: 0 when not used, -1 when write + * does not block, 1 simulate blocking */ cbq_T ch_cb_head; /* dummy node for per-request callbacks */ char_u *ch_callback; /* call when a msg is not handled */ partial_T *ch_partial; buf_T *ch_buffer; /* buffer to read from or write to */ + int ch_buf_append; /* write appended lines instead top-bot */ linenr_T ch_buf_top; /* next line to send */ linenr_T ch_buf_bot; /* last line to send */ } chanpart_T; @@ -1457,7 +1460,8 @@ struct channel_S { #define JO_ERR_BUF 0x2000000 /* "err_buf" (JO_OUT_BUF << 1) */ #define JO_IN_BUF 0x4000000 /* "in_buf" (JO_OUT_BUF << 2) */ #define JO_CHANNEL 0x8000000 /* "channel" */ -#define JO_ALL 0xfffffff +#define JO_BLOCK_WRITE 0x10000000 /* "block_write" */ +#define JO_ALL 0x7fffffff #define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE) #define JO_CB_ALL \ @@ -1499,6 +1503,7 @@ typedef struct int jo_timeout; int jo_out_timeout; int jo_err_timeout; + int jo_block_write; /* for testing only */ int jo_part; int jo_id; char_u jo_soe_buf[NUMBUFLEN]; diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index 8356ba7a5c..5e34ad2ca1 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -791,7 +791,7 @@ func Run_test_pipe_from_buffer(use_name) sp pipe-input call setline(1, ['echo one', 'echo two', 'echo three']) - let options = {'in_io': 'buffer'} + let options = {'in_io': 'buffer', 'block_write': 1} if a:use_name let options['in_name'] = 'pipe-input' else @@ -885,7 +885,8 @@ func Test_pipe_io_two_buffers() let job = job_start(s:python . " test_channel_pipe.py", \ {'in_io': 'buffer', 'in_name': 'pipe-input', 'in_top': 0, - \ 'out_io': 'buffer', 'out_name': 'pipe-output'}) + \ 'out_io': 'buffer', 'out_name': 'pipe-output', + \ 'block_write': 1}) call assert_equal("run", job_status(job)) try exe "normal Gaecho hello\" @@ -920,7 +921,8 @@ func Test_pipe_io_one_buffer() let job = job_start(s:python . " test_channel_pipe.py", \ {'in_io': 'buffer', 'in_name': 'pipe-io', 'in_top': 0, - \ 'out_io': 'buffer', 'out_name': 'pipe-io'}) + \ 'out_io': 'buffer', 'out_name': 'pipe-io', + \ 'block_write': 1}) call assert_equal("run", job_status(job)) try exe "normal Goecho hello\" diff --git a/src/version.c b/src/version.c index 9ba137583e..826ee1debe 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1669, /**/ 1668, /**/ diff --git a/src/vim.h b/src/vim.h index a2dc079613..36cc19a27a 100644 --- a/src/vim.h +++ b/src/vim.h @@ -493,13 +493,11 @@ typedef unsigned long u8char_T; /* long should be 32 bits or more */ #ifndef HAVE_SELECT # ifdef HAVE_SYS_POLL_H # include -# define HAVE_POLL # elif defined(WIN32) # define HAVE_SELECT # else # ifdef HAVE_POLL_H # include -# define HAVE_POLL # endif # endif #endif From a32095fc8fdf5fe3d487c86d9cc54adb1236731e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 19:27:13 +0200 Subject: [PATCH 05/18] patch 7.4.1670 Problem: Completion doesn't work well for a variable containing "#". Solution: Recognize the "#". (Watiko) --- src/eval.c | 6 ++++++ src/version.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/eval.c b/src/eval.c index ea7f9090aa..2c093d4154 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3399,6 +3399,12 @@ set_context_for_expression( got_eq = TRUE; xp->xp_context = EXPAND_EXPRESSION; } + else if (c == '#' + && xp->xp_context == EXPAND_EXPRESSION) + { + /* Autoload function/variable contains '#'. */ + break; + } else if ((c == '<' || c == '#') && xp->xp_context == EXPAND_FUNCTIONS && vim_strchr(xp->xp_pattern, '(') == NULL) diff --git a/src/version.c b/src/version.c index 826ee1debe..7039002fc5 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1670, /**/ 1669, /**/ From 61264d99692803eec76a171916ab9720c75536b0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 19:59:02 +0200 Subject: [PATCH 06/18] patch 7.4.1671 Problem: When help exists in multiple languages, adding @ab while "ab" is the default help language is unnecessary. Solution: Leave out "@ab" when not needed. (Ken Takata) --- src/ex_getln.c | 26 ++++++++++++++++++++++++-- src/version.c | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ex_getln.c b/src/ex_getln.c index 740c4b6cf9..11824907ee 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -4491,7 +4491,9 @@ expand_cmdline( #ifdef FEAT_MULTI_LANG /* - * Cleanup matches for help tags: remove "@en" if "en" is the only language. + * Cleanup matches for help tags: + * Remove "@ab" if the top of 'helplang' is "ab" and the language of the first + * tag matches it. Otherwise remove "@en" if "en" is the only language. */ static void cleanup_help_tags(int num_file, char_u **file); @@ -4500,11 +4502,28 @@ cleanup_help_tags(int num_file, char_u **file) { int i, j; int len; + char_u buf[4]; + char_u *p = buf; + + if (p_hlg[0] != NUL) + { + *p++ = '@'; + *p++ = p_hlg[0]; + *p++ = p_hlg[1]; + } + *p = NUL; for (i = 0; i < num_file; ++i) { len = (int)STRLEN(file[i]) - 3; - if (len > 0 && STRCMP(file[i] + len, "@en") == 0) + if (len <= 0) + continue; + if (i == 0 && STRCMP(file[i] + len, buf) == 0) + { + file[i][len] = NUL; + break; + } + else if (STRCMP(file[i] + len, "@en") == 0) { /* Sorting on priority means the same item in another language may * be anywhere. Search all items for a match up to the "@en". */ @@ -4514,7 +4533,10 @@ cleanup_help_tags(int num_file, char_u **file) && STRNCMP(file[i], file[j], len + 1) == 0) break; if (j == num_file) + { file[i][len] = NUL; + break; + } } } } diff --git a/src/version.c b/src/version.c index 7039002fc5..a26efec391 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1671, /**/ 1670, /**/ From e934e8f5c1c5c64411d98583ecbcf89e5ad01073 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 20:40:32 +0200 Subject: [PATCH 07/18] patch 7.4.1672 Problem: The Dvorak support is a bit difficult to install. Solution: Turn it into an optional package. --- runtime/macros/README.txt | 8 +- runtime/macros/dvorak | 164 ------------------ .../pack/dist/opt/dvorak/dvorak/disable.vim | 72 ++++++++ .../pack/dist/opt/dvorak/dvorak/enable.vim | 77 ++++++++ .../pack/dist/opt/dvorak/plugin/dvorak.vim | 16 ++ src/version.c | 2 + 6 files changed, 172 insertions(+), 167 deletions(-) delete mode 100644 runtime/macros/dvorak create mode 100644 runtime/pack/dist/opt/dvorak/dvorak/disable.vim create mode 100644 runtime/pack/dist/opt/dvorak/dvorak/enable.vim create mode 100644 runtime/pack/dist/opt/dvorak/plugin/dvorak.vim diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index f599c0a750..e749134836 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -11,8 +11,6 @@ urm Macros that simulate a simple computer: "Universal Register Machine" The other files contain some handy utilities. They also serve as examples for how to use Vi and Vim functionality. -dvorak for when you use a Dvorak keyboard - justify.vim user function for justifying text less.sh + less.vim make Vim work like less (or more) @@ -29,4 +27,8 @@ file_select.vim macros that make a handy file selector The matchit plugin has been moved to an optional package. To load it put this line in your vimrc file: - :packadd matchit + packadd! matchit + +The Dvorak supported has been moved to an optional package. To load it put +this line in your vimrc file: + packadd! dvorak diff --git a/runtime/macros/dvorak b/runtime/macros/dvorak deleted file mode 100644 index 0c75888703..0000000000 --- a/runtime/macros/dvorak +++ /dev/null @@ -1,164 +0,0 @@ -When using a dvorak keyboard this file may be of help to you. -These mappings have been made by Lawrence Kesteloot . -What they do is that the most often used keys, like hjkl, are put in a more -easy to use position. -It may take some time to learn using this. - -Put these lines in your .vimrc: --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -" Key to go into dvorak mode: -map ,d :source ~/.dvorak -" Key to get out of dvorak mode: -map ,q :source ~/.qwerty --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -write these lines into the file ~/.dvorak: --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -" Dvorak keyboard, only in insert mode and ex mode. -" You may want to add a list of map's too. -imap! a a -imap! b x -imap! c j -imap! d e -imap! e . -imap! f u -imap! g i -imap! h d -imap! i c -imap! j h -imap! k t -imap! l n -imap! m m -imap! n b -imap! o r -imap! p l -imap! q ' -imap! r p -imap! s o -imap! t y -imap! u g -imap! v k -imap! w , -imap! x q -imap! y f -imap! z ; -imap! ; s -imap! ' - -imap! " _ -imap! , w -imap! . v -imap! / z -imap! A A -imap! B X -imap! C J -imap! D E -imap! E > -imap! F U -imap! G I -imap! H D -imap! I C -imap! J H -imap! K T -imap! L N -imap! M M -imap! N B -imap! O R -imap! P L -imap! Q " -imap! R P -imap! S O -imap! T Y -imap! U G -imap! V K -imap! W < -imap! X Q -imap! Y F -imap! Z : -imap! < W -imap! > V -imap! ? Z -imap! : S -imap! [ / -imap! ] = -imap! { ? -imap! } + -imap! - [ -imap! _ { -imap! = ] -imap! + } --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -write these lines into the file ~/.qwerty --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -" Qwerty keyboard -unmap! a -unmap! b -unmap! c -unmap! d -unmap! e -unmap! f -unmap! g -unmap! h -unmap! i -unmap! j -unmap! k -unmap! l -unmap! m -unmap! n -unmap! o -unmap! p -unmap! q -unmap! r -unmap! s -unmap! t -unmap! u -unmap! v -unmap! w -unmap! x -unmap! y -unmap! z -unmap! ; -unmap! ' -unmap! \" -unmap! , -unmap! . -unmap! / -unmap! A -unmap! B -unmap! C -unmap! D -unmap! E -unmap! F -unmap! G -unmap! H -unmap! I -unmap! J -unmap! K -unmap! L -unmap! M -unmap! N -unmap! O -unmap! P -unmap! Q -unmap! R -unmap! S -unmap! T -unmap! U -unmap! V -unmap! W -unmap! X -unmap! Y -unmap! Z -unmap! < -unmap! > -unmap! ? -unmap! : -unmap! [ -unmap! ] -unmap! { -unmap! } -unmap! - -unmap! _ -unmap! = -unmap! + --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- diff --git a/runtime/pack/dist/opt/dvorak/dvorak/disable.vim b/runtime/pack/dist/opt/dvorak/dvorak/disable.vim new file mode 100644 index 0000000000..1e9b0702ff --- /dev/null +++ b/runtime/pack/dist/opt/dvorak/dvorak/disable.vim @@ -0,0 +1,72 @@ +" Back to Qwerty keyboard after using Dvorak. + +iunmap a +iunmap b +iunmap c +iunmap d +iunmap e +iunmap f +iunmap g +iunmap h +iunmap i +iunmap j +iunmap k +iunmap l +iunmap m +iunmap n +iunmap o +iunmap p +iunmap q +iunmap r +iunmap s +iunmap t +iunmap u +iunmap v +iunmap w +iunmap x +iunmap y +iunmap z +iunmap ; +iunmap ' +iunmap " +iunmap , +iunmap . +iunmap / +iunmap A +iunmap B +iunmap C +iunmap D +iunmap E +iunmap F +iunmap G +iunmap H +iunmap I +iunmap J +iunmap K +iunmap L +iunmap M +iunmap N +iunmap O +iunmap P +iunmap Q +iunmap R +iunmap S +iunmap T +iunmap U +iunmap V +iunmap W +iunmap X +iunmap Y +iunmap Z +iunmap < +iunmap > +iunmap ? +iunmap : +iunmap [ +iunmap ] +iunmap { +iunmap } +iunmap - +iunmap _ +iunmap = +iunmap + diff --git a/runtime/pack/dist/opt/dvorak/dvorak/enable.vim b/runtime/pack/dist/opt/dvorak/dvorak/enable.vim new file mode 100644 index 0000000000..8ff363fe97 --- /dev/null +++ b/runtime/pack/dist/opt/dvorak/dvorak/enable.vim @@ -0,0 +1,77 @@ +" Dvorak keyboard, only in Insert mode. +" +" Change "inoremap" to "map!" to also use in Ex mode. +" Also change disable.vim then: "iunmap" to "unmap!". +" +" You may want to add a list of map's too. + +inoremap a a +inoremap b x +inoremap c j +inoremap d e +inoremap e . +inoremap f u +inoremap g i +inoremap h d +inoremap i c +inoremap j h +inoremap k t +inoremap l n +inoremap m m +inoremap n b +inoremap o r +inoremap p l +inoremap q ' +inoremap r p +inoremap s o +inoremap t y +inoremap u g +inoremap v k +inoremap w , +inoremap x q +inoremap y f +inoremap z ; +inoremap ; s +inoremap ' - +inoremap " _ +inoremap , w +inoremap . v +inoremap / z +inoremap A A +inoremap B X +inoremap C J +inoremap D E +inoremap E > +inoremap F U +inoremap G I +inoremap H D +inoremap I C +inoremap J H +inoremap K T +inoremap L N +inoremap M M +inoremap N B +inoremap O R +inoremap P L +inoremap Q " +inoremap R P +inoremap S O +inoremap T Y +inoremap U G +inoremap V K +inoremap W < +inoremap X Q +inoremap Y F +inoremap Z : +inoremap < W +inoremap > V +inoremap ? Z +inoremap : S +inoremap [ / +inoremap ] = +inoremap { ? +inoremap } + +inoremap - [ +inoremap _ { +inoremap = ] +inoremap + } diff --git a/runtime/pack/dist/opt/dvorak/plugin/dvorak.vim b/runtime/pack/dist/opt/dvorak/plugin/dvorak.vim new file mode 100644 index 0000000000..c8d5d5c79f --- /dev/null +++ b/runtime/pack/dist/opt/dvorak/plugin/dvorak.vim @@ -0,0 +1,16 @@ +" When using a dvorak keyboard this file may be of help to you. +" These mappings have been made by Lawrence Kesteloot . +" What they do is that the most often used keys, like hjkl, are put in a more +" easy to use position. +" It may take some time to learn using this. + +if exists("g:loaded_dvorak_plugin") + finish +endif +let g:loaded_dvorak_plugin = 1 + +" Key to go into dvorak mode: +map ,d :runtime dvorak/enable.vim + +" Key to get out of dvorak mode: +map ,q :runtime dvorak/disable.vim diff --git a/src/version.c b/src/version.c index a26efec391..d36a51baa8 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1672, /**/ 1671, /**/ From 2946d0236dc9e23ec0050feacdb959b9ae5672a8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 20:53:08 +0200 Subject: [PATCH 08/18] patch 7.4.1673 Problem: The justify plugin has to be copied or sourced to be used. Solution: Turn it into a package. --- Filelist | 5 +- runtime/macros/README.txt | 14 +- runtime/macros/justify.vim | 319 +----------------- .../pack/dist/opt/justify/plugin/justify.vim | 316 +++++++++++++++++ src/version.c | 2 + 5 files changed, 333 insertions(+), 323 deletions(-) create mode 100644 runtime/pack/dist/opt/justify/plugin/justify.vim diff --git a/Filelist b/Filelist index d95c8f4142..cd55fe1584 100644 --- a/Filelist +++ b/Filelist @@ -483,7 +483,6 @@ RT_ALL = \ runtime/ftoff.vim \ runtime/gvimrc_example.vim \ runtime/macros/README.txt \ - runtime/macros/dvorak \ runtime/macros/editexisting.vim \ runtime/macros/hanoi/click.me \ runtime/macros/hanoi/hanoi.vim \ @@ -524,6 +523,10 @@ RT_ALL = \ runtime/tutor/tutor \ runtime/tutor/tutor.vim \ runtime/vimrc_example.vim \ + runtime/pack/dist/opt/dvorak/plugin/dvorak.vim \ + runtime/pack/dist/opt/dvorak/dvorak/enable.vim \ + runtime/pack/dist/opt/dvorak/dvorak/disable.vim \ + runtime/pack/dist/opt/justify/plugin/justify.vim \ runtime/pack/dist/opt/matchit/plugin/matchit.vim \ runtime/pack/dist/opt/matchit/doc/matchit.txt \ runtime/pack/dist/opt/matchit/doc/tags \ diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index e749134836..884fe53510 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -11,8 +11,6 @@ urm Macros that simulate a simple computer: "Universal Register Machine" The other files contain some handy utilities. They also serve as examples for how to use Vi and Vim functionality. -justify.vim user function for justifying text - less.sh + less.vim make Vim work like less (or more) shellmenu.vim menus for editing shell scripts in the GUI version @@ -25,10 +23,14 @@ editexisting.vim when editing a file that is already edited with This one is only for Unix. file_select.vim macros that make a handy file selector +The Dvorak support has been moved to an optional package. To load it put this +line in your vimrc file: + packadd! dvorak + +The support for justifying test has been moved to an optional package. To +load it put this line in your vimrc file: + packadd! justify + The matchit plugin has been moved to an optional package. To load it put this line in your vimrc file: packadd! matchit - -The Dvorak supported has been moved to an optional package. To load it put -this line in your vimrc file: - packadd! dvorak diff --git a/runtime/macros/justify.vim b/runtime/macros/justify.vim index 4ef3bf95fa..011a911401 100644 --- a/runtime/macros/justify.vim +++ b/runtime/macros/justify.vim @@ -1,316 +1,3 @@ -" Function to left and right align text. -" -" Written by: Preben "Peppe" Guldberg -" Created: 980806 14:13 (or around that time anyway) -" Revised: 001103 00:36 (See "Revisions" below) - - -" function Justify( [ textwidth [, maxspaces [, indent] ] ] ) -" -" Justify() will left and right align a line by filling in an -" appropriate amount of spaces. Extra spaces are added to existing -" spaces starting from the right side of the line. As an example, the -" following documentation has been justified. -" -" The function takes the following arguments: - -" textwidth argument -" ------------------ -" If not specified, the value of the 'textwidth' option is used. If -" 'textwidth' is zero a value of 80 is used. -" -" Additionally the arguments 'tw' and '' are accepted. The value of -" 'textwidth' will be used. These are handy, if you just want to specify -" the maxspaces argument. - -" maxspaces argument -" ------------------ -" If specified, alignment will only be done, if the longest space run -" after alignment is no longer than maxspaces. -" -" An argument of '' is accepted, should the user like to specify all -" arguments. -" -" To aid user defined commands, negative values are accepted aswell. -" Using a negative value specifies the default behaviour: any length of -" space runs will be used to justify the text. - -" indent argument -" --------------- -" This argument specifies how a line should be indented. The default is -" to keep the current indentation. -" -" Negative values: Keep current amount of leading whitespace. -" Positive values: Indent all lines with leading whitespace using this -" amount of whitespace. -" -" Note that the value 0, needs to be quoted as a string. This value -" leads to a left flushed text. -" -" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be -" added. In this case, if the value of indent is positive, the amount of -" whitespace to be added will be multiplied by the value of the -" 'shiftwidth' and 'tabstop' settings. If these units are used, the -" argument must be given as a string, eg. Justify('','','2sw'). -" -" If the values of 'sw' or 'tw' are negative, they are treated as if -" they were 0, which means that the text is flushed left. There is no -" check if a negative number prefix is used to change the sign of a -" negative 'sw' or 'ts' value. -" -" As with the other arguments, '' may be used to get the default -" behaviour. - - -" Notes: -" -" If the line, adjusted for space runs and leading/trailing whitespace, -" is wider than the used textwidth, the line will be left untouched (no -" whitespace removed). This should be equivalent to the behaviour of -" :left, :right and :center. -" -" If the resulting line is shorter than the used textwidth it is left -" untouched. -" -" All space runs in the line are truncated before the alignment is -" carried out. -" -" If you have set 'noexpandtab', :retab! is used to replace space runs -" with whitespace using the value of 'tabstop'. This should be -" conformant with :left, :right and :center. -" -" If joinspaces is set, an extra space is added after '.', '?' and '!'. -" If 'cpooptions' include 'j', extra space is only added after '.'. -" (This may on occasion conflict with maxspaces.) - - -" Related mappings: -" -" Mappings that will align text using the current text width, using at -" most four spaces in a space run and keeping current indentation. -nmap _j :%call Justify('tw',4) -vmap _j :call Justify('tw',4) -" -" Mappings that will remove space runs and format lines (might be useful -" prior to aligning the text). -nmap ,gq :%s/\s\+/ /ggq1G -vmap ,gq :s/\s\+/ /ggvgq - - -" User defined command: -" -" The following is an ex command that works as a shortcut to the Justify -" function. Arguments to Justify() can be added after the command. -com! -range -nargs=* Justify ,call Justify() -" -" The following commands are all equivalent: -" -" 1. Simplest use of Justify(): -" :call Justify() -" :Justify -" -" 2. The _j mapping above via the ex command: -" :%Justify tw 4 -" -" 3. Justify visualised text at 72nd column while indenting all -" previously indented text two shiftwidths -" :'<,'>call Justify(72,'','2sw') -" :'<,'>Justify 72 -1 2sw -" -" This documentation has been justified using the following command: -":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" / - -" Revisions: -" 001103: If 'joinspaces' was set, calculations could be wrong. -" Tabs at start of line could also lead to errors. -" Use setline() instead of "exec 's/foo/bar/' - safer. -" Cleaned up the code a bit. -" -" Todo: Convert maps to the new script specific form - -" Error function -function! Justify_error(message) - echohl Error - echo "Justify([tw, [maxspaces [, indent]]]): " . a:message - echohl None -endfunction - - -" Now for the real thing -function! Justify(...) range - - if a:0 > 3 - call Justify_error("Too many arguments (max 3)") - return 1 - endif - - " Set textwidth (accept 'tw' and '' as arguments) - if a:0 >= 1 - if a:1 =~ '^\(tw\)\=$' - let tw = &tw - elseif a:1 =~ '^\d\+$' - let tw = a:1 - else - call Justify_error("tw must be a number (>0), '' or 'tw'") - return 2 - endif - else - let tw = &tw - endif - if tw == 0 - let tw = 80 - endif - - " Set maximum number of spaces between WORDs - if a:0 >= 2 - if a:2 == '' - let maxspaces = tw - elseif a:2 =~ '^-\d\+$' - let maxspaces = tw - elseif a:2 =~ '^\d\+$' - let maxspaces = a:2 - else - call Justify_error("maxspaces must be a number or ''") - return 3 - endif - else - let maxspaces = tw - endif - if maxspaces <= 1 - call Justify_error("maxspaces should be larger than 1") - return 4 - endif - - " Set the indentation style (accept sw and ts units) - let indent_fix = '' - if a:0 >= 3 - if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$' - let indent = -1 - elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$' - let indent = 0 - elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$' - let indent = substitute(a:3, '\D', '', 'g') - elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$' - let indent = 1 - else - call Justify_error("indent: a number with 'sw'/'ts' unit") - return 5 - endif - if indent >= 0 - while indent > 0 - let indent_fix = indent_fix . ' ' - let indent = indent - 1 - endwhile - let indent_sw = 0 - if a:3 =~ '\(shiftwidth\|sw\)' - let indent_sw = &sw - elseif a:3 =~ '\(tabstop\|ts\)' - let indent_sw = &ts - endif - let indent_fix2 = '' - while indent_sw > 0 - let indent_fix2 = indent_fix2 . indent_fix - let indent_sw = indent_sw - 1 - endwhile - let indent_fix = indent_fix2 - endif - else - let indent = -1 - endif - - " Avoid substitution reports - let save_report = &report - set report=1000000 - - " Check 'joinspaces' and 'cpo' - if &js == 1 - if &cpo =~ 'j' - let join_str = '\(\. \)' - else - let join_str = '\([.!?!] \)' - endif - endif - - let cur = a:firstline - while cur <= a:lastline - - let str_orig = getline(cur) - let save_et = &et - set et - exec cur . "retab" - let &et = save_et - let str = getline(cur) - - let indent_str = indent_fix - let indent_n = strlen(indent_str) - " Shall we remember the current indentation - if indent < 0 - let indent_orig = matchstr(str_orig, '^\s*') - if strlen(indent_orig) > 0 - let indent_str = indent_orig - let indent_n = strlen(matchstr(str, '^\s*')) - endif - endif - - " Trim trailing, leading and running whitespace - let str = substitute(str, '\s\+$', '', '') - let str = substitute(str, '^\s\+', '', '') - let str = substitute(str, '\s\+', ' ', 'g') - let str_n = strdisplaywidth(str) - - " Possible addition of space after punctuation - if exists("join_str") - let str = substitute(str, join_str, '\1 ', 'g') - endif - let join_n = strdisplaywidth(str) - str_n - - " Can extraspaces be added? - " Note that str_n may be less than strlen(str) [joinspaces above] - if strdisplaywidth(str) <= tw - indent_n && str_n > 0 - " How many spaces should be added - let s_add = tw - str_n - indent_n - join_n - let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n - let s_dup = s_add / s_nr - let s_mod = s_add % s_nr - - " Test if the changed line fits with tw - if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw - - " Duplicate spaces - while s_dup > 0 - let str = substitute(str, '\( \+\)', ' \1', 'g') - let s_dup = s_dup - 1 - endwhile - - " Add extra spaces from the end - while s_mod > 0 - let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '') - let s_mod = s_mod - 1 - endwhile - - " Indent the line - if indent_n > 0 - let str = substitute(str, '^', indent_str, '' ) - endif - - " Replace the line - call setline(cur, str) - - " Convert to whitespace - if &et == 0 - exec cur . 'retab!' - endif - - endif " Change of line - endif " Possible change - - let cur = cur + 1 - endwhile - - norm ^ - - let &report = save_report - -endfunction - -" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai +" Load the justify package. +" For those users who were loading the justify plugin from here. +packadd justify diff --git a/runtime/pack/dist/opt/justify/plugin/justify.vim b/runtime/pack/dist/opt/justify/plugin/justify.vim new file mode 100644 index 0000000000..4ef3bf95fa --- /dev/null +++ b/runtime/pack/dist/opt/justify/plugin/justify.vim @@ -0,0 +1,316 @@ +" Function to left and right align text. +" +" Written by: Preben "Peppe" Guldberg +" Created: 980806 14:13 (or around that time anyway) +" Revised: 001103 00:36 (See "Revisions" below) + + +" function Justify( [ textwidth [, maxspaces [, indent] ] ] ) +" +" Justify() will left and right align a line by filling in an +" appropriate amount of spaces. Extra spaces are added to existing +" spaces starting from the right side of the line. As an example, the +" following documentation has been justified. +" +" The function takes the following arguments: + +" textwidth argument +" ------------------ +" If not specified, the value of the 'textwidth' option is used. If +" 'textwidth' is zero a value of 80 is used. +" +" Additionally the arguments 'tw' and '' are accepted. The value of +" 'textwidth' will be used. These are handy, if you just want to specify +" the maxspaces argument. + +" maxspaces argument +" ------------------ +" If specified, alignment will only be done, if the longest space run +" after alignment is no longer than maxspaces. +" +" An argument of '' is accepted, should the user like to specify all +" arguments. +" +" To aid user defined commands, negative values are accepted aswell. +" Using a negative value specifies the default behaviour: any length of +" space runs will be used to justify the text. + +" indent argument +" --------------- +" This argument specifies how a line should be indented. The default is +" to keep the current indentation. +" +" Negative values: Keep current amount of leading whitespace. +" Positive values: Indent all lines with leading whitespace using this +" amount of whitespace. +" +" Note that the value 0, needs to be quoted as a string. This value +" leads to a left flushed text. +" +" Additionally units of 'shiftwidth'/'sw' and 'tabstop'/'ts' may be +" added. In this case, if the value of indent is positive, the amount of +" whitespace to be added will be multiplied by the value of the +" 'shiftwidth' and 'tabstop' settings. If these units are used, the +" argument must be given as a string, eg. Justify('','','2sw'). +" +" If the values of 'sw' or 'tw' are negative, they are treated as if +" they were 0, which means that the text is flushed left. There is no +" check if a negative number prefix is used to change the sign of a +" negative 'sw' or 'ts' value. +" +" As with the other arguments, '' may be used to get the default +" behaviour. + + +" Notes: +" +" If the line, adjusted for space runs and leading/trailing whitespace, +" is wider than the used textwidth, the line will be left untouched (no +" whitespace removed). This should be equivalent to the behaviour of +" :left, :right and :center. +" +" If the resulting line is shorter than the used textwidth it is left +" untouched. +" +" All space runs in the line are truncated before the alignment is +" carried out. +" +" If you have set 'noexpandtab', :retab! is used to replace space runs +" with whitespace using the value of 'tabstop'. This should be +" conformant with :left, :right and :center. +" +" If joinspaces is set, an extra space is added after '.', '?' and '!'. +" If 'cpooptions' include 'j', extra space is only added after '.'. +" (This may on occasion conflict with maxspaces.) + + +" Related mappings: +" +" Mappings that will align text using the current text width, using at +" most four spaces in a space run and keeping current indentation. +nmap _j :%call Justify('tw',4) +vmap _j :call Justify('tw',4) +" +" Mappings that will remove space runs and format lines (might be useful +" prior to aligning the text). +nmap ,gq :%s/\s\+/ /ggq1G +vmap ,gq :s/\s\+/ /ggvgq + + +" User defined command: +" +" The following is an ex command that works as a shortcut to the Justify +" function. Arguments to Justify() can be added after the command. +com! -range -nargs=* Justify ,call Justify() +" +" The following commands are all equivalent: +" +" 1. Simplest use of Justify(): +" :call Justify() +" :Justify +" +" 2. The _j mapping above via the ex command: +" :%Justify tw 4 +" +" 3. Justify visualised text at 72nd column while indenting all +" previously indented text two shiftwidths +" :'<,'>call Justify(72,'','2sw') +" :'<,'>Justify 72 -1 2sw +" +" This documentation has been justified using the following command: +":se et|kz|1;/^" function Justify(/+,'z-g/^" /s/^" //|call Justify(70,3)|s/^/" / + +" Revisions: +" 001103: If 'joinspaces' was set, calculations could be wrong. +" Tabs at start of line could also lead to errors. +" Use setline() instead of "exec 's/foo/bar/' - safer. +" Cleaned up the code a bit. +" +" Todo: Convert maps to the new script specific form + +" Error function +function! Justify_error(message) + echohl Error + echo "Justify([tw, [maxspaces [, indent]]]): " . a:message + echohl None +endfunction + + +" Now for the real thing +function! Justify(...) range + + if a:0 > 3 + call Justify_error("Too many arguments (max 3)") + return 1 + endif + + " Set textwidth (accept 'tw' and '' as arguments) + if a:0 >= 1 + if a:1 =~ '^\(tw\)\=$' + let tw = &tw + elseif a:1 =~ '^\d\+$' + let tw = a:1 + else + call Justify_error("tw must be a number (>0), '' or 'tw'") + return 2 + endif + else + let tw = &tw + endif + if tw == 0 + let tw = 80 + endif + + " Set maximum number of spaces between WORDs + if a:0 >= 2 + if a:2 == '' + let maxspaces = tw + elseif a:2 =~ '^-\d\+$' + let maxspaces = tw + elseif a:2 =~ '^\d\+$' + let maxspaces = a:2 + else + call Justify_error("maxspaces must be a number or ''") + return 3 + endif + else + let maxspaces = tw + endif + if maxspaces <= 1 + call Justify_error("maxspaces should be larger than 1") + return 4 + endif + + " Set the indentation style (accept sw and ts units) + let indent_fix = '' + if a:0 >= 3 + if (a:3 == '') || a:3 =~ '^-[1-9]\d*\(shiftwidth\|sw\|tabstop\|ts\)\=$' + let indent = -1 + elseif a:3 =~ '^-\=0\(shiftwidth\|sw\|tabstop\|ts\)\=$' + let indent = 0 + elseif a:3 =~ '^\d\+\(shiftwidth\|sw\|tabstop\|ts\)\=$' + let indent = substitute(a:3, '\D', '', 'g') + elseif a:3 =~ '^\(shiftwidth\|sw\|tabstop\|ts\)$' + let indent = 1 + else + call Justify_error("indent: a number with 'sw'/'ts' unit") + return 5 + endif + if indent >= 0 + while indent > 0 + let indent_fix = indent_fix . ' ' + let indent = indent - 1 + endwhile + let indent_sw = 0 + if a:3 =~ '\(shiftwidth\|sw\)' + let indent_sw = &sw + elseif a:3 =~ '\(tabstop\|ts\)' + let indent_sw = &ts + endif + let indent_fix2 = '' + while indent_sw > 0 + let indent_fix2 = indent_fix2 . indent_fix + let indent_sw = indent_sw - 1 + endwhile + let indent_fix = indent_fix2 + endif + else + let indent = -1 + endif + + " Avoid substitution reports + let save_report = &report + set report=1000000 + + " Check 'joinspaces' and 'cpo' + if &js == 1 + if &cpo =~ 'j' + let join_str = '\(\. \)' + else + let join_str = '\([.!?!] \)' + endif + endif + + let cur = a:firstline + while cur <= a:lastline + + let str_orig = getline(cur) + let save_et = &et + set et + exec cur . "retab" + let &et = save_et + let str = getline(cur) + + let indent_str = indent_fix + let indent_n = strlen(indent_str) + " Shall we remember the current indentation + if indent < 0 + let indent_orig = matchstr(str_orig, '^\s*') + if strlen(indent_orig) > 0 + let indent_str = indent_orig + let indent_n = strlen(matchstr(str, '^\s*')) + endif + endif + + " Trim trailing, leading and running whitespace + let str = substitute(str, '\s\+$', '', '') + let str = substitute(str, '^\s\+', '', '') + let str = substitute(str, '\s\+', ' ', 'g') + let str_n = strdisplaywidth(str) + + " Possible addition of space after punctuation + if exists("join_str") + let str = substitute(str, join_str, '\1 ', 'g') + endif + let join_n = strdisplaywidth(str) - str_n + + " Can extraspaces be added? + " Note that str_n may be less than strlen(str) [joinspaces above] + if strdisplaywidth(str) <= tw - indent_n && str_n > 0 + " How many spaces should be added + let s_add = tw - str_n - indent_n - join_n + let s_nr = strlen(substitute(str, '\S', '', 'g') ) - join_n + let s_dup = s_add / s_nr + let s_mod = s_add % s_nr + + " Test if the changed line fits with tw + if 0 <= (str_n + (maxspaces - 1)*s_nr + indent_n) - tw + + " Duplicate spaces + while s_dup > 0 + let str = substitute(str, '\( \+\)', ' \1', 'g') + let s_dup = s_dup - 1 + endwhile + + " Add extra spaces from the end + while s_mod > 0 + let str = substitute(str, '\(\(\s\+\S\+\)\{' . s_mod . '}\)$', ' \1', '') + let s_mod = s_mod - 1 + endwhile + + " Indent the line + if indent_n > 0 + let str = substitute(str, '^', indent_str, '' ) + endif + + " Replace the line + call setline(cur, str) + + " Convert to whitespace + if &et == 0 + exec cur . 'retab!' + endif + + endif " Change of line + endif " Possible change + + let cur = cur + 1 + endwhile + + norm ^ + + let &report = save_report + +endfunction + +" EOF vim: tw=78 ts=8 sw=4 sts=4 noet ai diff --git a/src/version.c b/src/version.c index d36a51baa8..36cfa653f6 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1673, /**/ 1672, /**/ From cf2d8dee5117b9add3a3f5fc91b3569437e7d359 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 21:04:37 +0200 Subject: [PATCH 09/18] patch 7.4.1674 Problem: The editexisting plugin has to be copied or sourced to be used. Solution: Turn it into a package. --- Filelist | 1 + runtime/macros/README.txt | 22 ++-- .../opt/editexisting/plugin/editexisting.vim | 114 ++++++++++++++++++ src/version.c | 2 + 4 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 runtime/pack/dist/opt/editexisting/plugin/editexisting.vim diff --git a/Filelist b/Filelist index cd55fe1584..b64658edde 100644 --- a/Filelist +++ b/Filelist @@ -526,6 +526,7 @@ RT_ALL = \ runtime/pack/dist/opt/dvorak/plugin/dvorak.vim \ runtime/pack/dist/opt/dvorak/dvorak/enable.vim \ runtime/pack/dist/opt/dvorak/dvorak/disable.vim \ + runtime/pack/dist/opt/editexisting/plugin/editexisting.vim \ runtime/pack/dist/opt/justify/plugin/justify.vim \ runtime/pack/dist/opt/matchit/plugin/matchit.vim \ runtime/pack/dist/opt/matchit/doc/matchit.txt \ diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index 884fe53510..a805007846 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -17,20 +17,20 @@ shellmenu.vim menus for editing shell scripts in the GUI version swapmous.vim swap left and right mouse buttons -editexisting.vim when editing a file that is already edited with - another Vim instance +editexisting.vim This one is only for Unix. file_select.vim macros that make a handy file selector -The Dvorak support has been moved to an optional package. To load it put this -line in your vimrc file: - packadd! dvorak -The support for justifying test has been moved to an optional package. To -load it put this line in your vimrc file: - packadd! justify +The following have been moved to an optional package. Add the command to your +vimrc file to use the package: -The matchit plugin has been moved to an optional package. To load it put this -line in your vimrc file: - packadd! matchit +packadd! dvorak Dvorak keyboard support; adds mappings + +packadd! editexisting when editing a file that is already edited with + another Vim instance, go to that Vim instance + +packadd! justify justifying text. + +packadd! matchit makes the % command work better diff --git a/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim b/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim new file mode 100644 index 0000000000..d9877a0591 --- /dev/null +++ b/runtime/pack/dist/opt/editexisting/plugin/editexisting.vim @@ -0,0 +1,114 @@ +" Vim Plugin: Edit the file with an existing Vim if possible +" Maintainer: Bram Moolenaar +" Last Change: 2016 Mar 28 + +" To use add ":packadd! editexisting" in your vimrc file. + +" This plugin serves two purposes: +" 1. On startup, if we were invoked with one file name argument and the file +" is not modified then try to find another Vim instance that is editing +" this file. If there is one then bring it to the foreground and exit. +" 2. When a file is edited and a swap file exists for it, try finding that +" other Vim and bring it to the foreground. Requires Vim 7, because it +" uses the SwapExists autocommand event. + +" Function that finds the Vim instance that is editing "filename" and brings +" it to the foreground. +func s:EditElsewhere(filename) + let fname_esc = substitute(a:filename, "'", "''", "g") + + let servers = serverlist() + while servers != '' + " Get next server name in "servername"; remove it from "servers". + let i = match(servers, "\n") + if i == -1 + let servername = servers + let servers = '' + else + let servername = strpart(servers, 0, i) + let servers = strpart(servers, i + 1) + endif + + " Skip ourselves. + if servername ==? v:servername + continue + endif + + " Check if this server is editing our file. + if remote_expr(servername, "bufloaded('" . fname_esc . "')") + " Yes, bring it to the foreground. + if has("win32") + call remote_foreground(servername) + endif + call remote_expr(servername, "foreground()") + + if remote_expr(servername, "exists('*EditExisting')") + " Make sure the file is visible in a window (not hidden). + " If v:swapcommand exists and is set, send it to the server. + if exists("v:swapcommand") + let c = substitute(v:swapcommand, "'", "''", "g") + call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')") + else + call remote_expr(servername, "EditExisting('" . fname_esc . "', '')") + endif + endif + + if !(has('vim_starting') && has('gui_running') && has('gui_win32')) + " Tell the user what is happening. Not when the GUI is starting + " though, it would result in a message box. + echomsg "File is being edited by " . servername + sleep 2 + endif + return 'q' + endif + endwhile + return '' +endfunc + +" When the plugin is loaded and there is one file name argument: Find another +" Vim server that is editing this file right now. +if argc() == 1 && !&modified + if s:EditElsewhere(expand("%:p")) == 'q' + quit + endif +endif + +" Setup for handling the situation that an existing swap file is found. +try + au! SwapExists * let v:swapchoice = s:EditElsewhere(expand(":p")) +catch + " Without SwapExists we don't do anything for ":edit" commands +endtry + +" Function used on the server to make the file visible and possibly execute a +" command. +func! EditExisting(fname, command) + " Get the window number of the file in the current tab page. + let winnr = bufwinnr(a:fname) + if winnr <= 0 + " Not found, look in other tab pages. + let bufnr = bufnr(a:fname) + for i in range(tabpagenr('$')) + if index(tabpagebuflist(i + 1), bufnr) >= 0 + " Make this tab page the current one and find the window number. + exe 'tabnext ' . (i + 1) + let winnr = bufwinnr(a:fname) + break + endif + endfor + endif + + if winnr > 0 + exe winnr . "wincmd w" + elseif exists('*fnameescape') + exe "split " . fnameescape(a:fname) + else + exe "split " . escape(a:fname, " \t\n*?[{`$\\%#'\"|!<") + endif + + if a:command != '' + exe "normal! " . a:command + endif + + redraw +endfunc diff --git a/src/version.c b/src/version.c index 36cfa653f6..68991898d3 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1674, /**/ 1673, /**/ From e101204906e10f1e100e2f9017985c61f26b03ac Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 21:10:49 +0200 Subject: [PATCH 10/18] patch 7.4.1675 Problem: The swapmous plugin has to be copied or sourced to be used. Solution: Turn it into the swapmouse package. --- Filelist | 1 + runtime/macros/README.txt | 5 ++-- runtime/macros/swapmous.vim | 25 +++---------------- .../dist/opt/swapmouse/plugin/swapmouse.vim | 22 ++++++++++++++++ src/version.c | 2 ++ 5 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim diff --git a/Filelist b/Filelist index b64658edde..65ebe4c4af 100644 --- a/Filelist +++ b/Filelist @@ -531,6 +531,7 @@ RT_ALL = \ runtime/pack/dist/opt/matchit/plugin/matchit.vim \ runtime/pack/dist/opt/matchit/doc/matchit.txt \ runtime/pack/dist/opt/matchit/doc/tags \ + runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim \ # runtime files for all distributions without CR-NL translation RT_ALL_BIN = \ diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index a805007846..a134112aaf 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -15,9 +15,6 @@ less.sh + less.vim make Vim work like less (or more) shellmenu.vim menus for editing shell scripts in the GUI version -swapmous.vim swap left and right mouse buttons - -editexisting.vim This one is only for Unix. file_select.vim macros that make a handy file selector @@ -34,3 +31,5 @@ packadd! editexisting when editing a file that is already edited with packadd! justify justifying text. packadd! matchit makes the % command work better + +packadd! swapmouse swap left and right mouse buttons diff --git a/runtime/macros/swapmous.vim b/runtime/macros/swapmous.vim index 8b85be050b..5884d83473 100644 --- a/runtime/macros/swapmous.vim +++ b/runtime/macros/swapmous.vim @@ -1,22 +1,3 @@ -" These macros swap the left and right mouse buttons (for left handed) -" Don't forget to do ":set mouse=a" or the mouse won't work at all -noremap -noremap <2-LeftMouse> <2-RightMouse> -noremap <3-LeftMouse> <3-RightMouse> -noremap <4-LeftMouse> <4-RightMouse> -noremap -noremap -noremap -noremap <2-RightMouse> <2-LeftMouse> -noremap <3-RightMouse> <3-LeftMouse> -noremap <4-RightMouse> <4-LeftMouse> -noremap -noremap -noremap g -noremap g -noremap! -noremap! -noremap! -noremap! -noremap! -noremap! +" Load the swapmouse package. +" For those users who were loading the swapmous plugin from here. +packadd swapmouse diff --git a/runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim b/runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim new file mode 100644 index 0000000000..8b85be050b --- /dev/null +++ b/runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim @@ -0,0 +1,22 @@ +" These macros swap the left and right mouse buttons (for left handed) +" Don't forget to do ":set mouse=a" or the mouse won't work at all +noremap +noremap <2-LeftMouse> <2-RightMouse> +noremap <3-LeftMouse> <3-RightMouse> +noremap <4-LeftMouse> <4-RightMouse> +noremap +noremap +noremap +noremap <2-RightMouse> <2-LeftMouse> +noremap <3-RightMouse> <3-LeftMouse> +noremap <4-RightMouse> <4-LeftMouse> +noremap +noremap +noremap g +noremap g +noremap! +noremap! +noremap! +noremap! +noremap! +noremap! diff --git a/src/version.c b/src/version.c index 68991898d3..70a5969a93 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1675, /**/ 1674, /**/ From fead3ac9a35e0fc358141d3eb19574cd8a3ecb55 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 21:26:47 +0200 Subject: [PATCH 11/18] patch 7.4.1676 Problem: The shellmenu plugin has to be copied or sourced to be used. Solution: Turn it into a package. --- Filelist | 1 + runtime/macros/README.txt | 4 +- runtime/macros/shellmenu.vim | 97 +------------------ .../dist/opt/shellmenu/plugin/shellmenu.vim | 94 ++++++++++++++++++ src/version.c | 2 + 5 files changed, 102 insertions(+), 96 deletions(-) create mode 100644 runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim diff --git a/Filelist b/Filelist index 65ebe4c4af..1af664dc8f 100644 --- a/Filelist +++ b/Filelist @@ -531,6 +531,7 @@ RT_ALL = \ runtime/pack/dist/opt/matchit/plugin/matchit.vim \ runtime/pack/dist/opt/matchit/doc/matchit.txt \ runtime/pack/dist/opt/matchit/doc/tags \ + runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim \ runtime/pack/dist/opt/swapmouse/plugin/swapmouse.vim \ # runtime files for all distributions without CR-NL translation diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index a134112aaf..01635460d4 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -13,8 +13,6 @@ how to use Vi and Vim functionality. less.sh + less.vim make Vim work like less (or more) -shellmenu.vim menus for editing shell scripts in the GUI version - This one is only for Unix. file_select.vim macros that make a handy file selector @@ -32,4 +30,6 @@ packadd! justify justifying text. packadd! matchit makes the % command work better +packadd! shellmenu menus for editing shell scripts in the GUI version + packadd! swapmouse swap left and right mouse buttons diff --git a/runtime/macros/shellmenu.vim b/runtime/macros/shellmenu.vim index 6175d1d9a6..4eb72a556a 100644 --- a/runtime/macros/shellmenu.vim +++ b/runtime/macros/shellmenu.vim @@ -1,94 +1,3 @@ -" When you're writing shell scripts and you are in doubt which test to use, -" which shell environment variables are defined, what the syntax of the case -" statement is, and you need to invoke 'man sh'? -" -" Your problems are over now! -" -" Attached is a Vim script file for turning gvim into a shell script editor. -" It may also be used as an example how to use menus in Vim. -" -" Written by: Lennart Schultz - -imenu Stmts.for for in do doneki kk0elli -imenu Stmts.case case in ) ;; esacbki k0elli -imenu Stmts.if if then fiki kk0elli -imenu Stmts.if-else if then else fiki kki kk0elli -imenu Stmts.elif elif then ki kk0elli -imenu Stmts.while while do doneki kk0elli -imenu Stmts.break break -imenu Stmts.continue continue -imenu Stmts.function () { }ki k0i -imenu Stmts.return return -imenu Stmts.return-true return 0 -imenu Stmts.return-false return 1 -imenu Stmts.exit exit -imenu Stmts.shift shift -imenu Stmts.trap trap -imenu Test.existence [ -e ]hi -imenu Test.existence - file [ -f ]hi -imenu Test.existence - file (not empty) [ -s ]hi -imenu Test.existence - directory [ -d ]hi -imenu Test.existence - executable [ -x ]hi -imenu Test.existence - readable [ -r ]hi -imenu Test.existence - writable [ -w ]hi -imenu Test.String is empty [ x = "x$" ]hhi -imenu Test.String is not empty [ x != "x$" ]hhi -imenu Test.Strings is equal [ "" = "" ]hhhhhhhi -imenu Test.Strings is not equal [ "" != "" ]hhhhhhhhi -imenu Test.Values is greater than [ -gt ]hhhhhhi -imenu Test.Values is greater equal [ -ge ]hhhhhhi -imenu Test.Values is equal [ -eq ]hhhhhhi -imenu Test.Values is not equal [ -ne ]hhhhhhi -imenu Test.Values is less than [ -lt ]hhhhhhi -imenu Test.Values is less equal [ -le ]hhhhhhi -imenu ParmSub.Substitute word if parm not set ${:-}hhi -imenu ParmSub.Set parm to word if not set ${:=}hhi -imenu ParmSub.Substitute word if parm set else nothing ${:+}hhi -imenu ParmSub.If parm not set print word and exit ${:?}hhi -imenu SpShVars.Number of positional parameters ${#} -imenu SpShVars.All positional parameters (quoted spaces) ${*} -imenu SpShVars.All positional parameters (unquoted spaces) ${@} -imenu SpShVars.Flags set ${-} -imenu SpShVars.Return code of last command ${?} -imenu SpShVars.Process number of this shell ${$} -imenu SpShVars.Process number of last background command ${!} -imenu Environ.HOME ${HOME} -imenu Environ.PATH ${PATH} -imenu Environ.CDPATH ${CDPATH} -imenu Environ.MAIL ${MAIL} -imenu Environ.MAILCHECK ${MAILCHECK} -imenu Environ.PS1 ${PS1} -imenu Environ.PS2 ${PS2} -imenu Environ.IFS ${IFS} -imenu Environ.SHACCT ${SHACCT} -imenu Environ.SHELL ${SHELL} -imenu Environ.LC_CTYPE ${LC_CTYPE} -imenu Environ.LC_MESSAGES ${LC_MESSAGES} -imenu Builtins.cd cd -imenu Builtins.echo echo -imenu Builtins.eval eval -imenu Builtins.exec exec -imenu Builtins.export export -imenu Builtins.getopts getopts -imenu Builtins.hash hash -imenu Builtins.newgrp newgrp -imenu Builtins.pwd pwd -imenu Builtins.read read -imenu Builtins.readonly readonly -imenu Builtins.return return -imenu Builtins.times times -imenu Builtins.type type -imenu Builtins.umask umask -imenu Builtins.wait wait -imenu Set.set set -imenu Set.unset unset -imenu Set.mark modified or modified variables set -a -imenu Set.exit when command returns non-zero exit code set -e -imenu Set.Disable file name generation set -f -imenu Set.remember function commands set -h -imenu Set.All keyword arguments are placed in the environment set -k -imenu Set.Read commands but do not execute them set -n -imenu Set.Exit after reading and executing one command set -t -imenu Set.Treat unset variables as an error when substituting set -u -imenu Set.Print shell input lines as they are read set -v -imenu Set.Print commands and their arguments as they are executed set -x +" Load the shellmenu package. +" For those users who were loading the shellmenu plugin from here. +packadd shellmenu diff --git a/runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim b/runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim new file mode 100644 index 0000000000..6175d1d9a6 --- /dev/null +++ b/runtime/pack/dist/opt/shellmenu/plugin/shellmenu.vim @@ -0,0 +1,94 @@ +" When you're writing shell scripts and you are in doubt which test to use, +" which shell environment variables are defined, what the syntax of the case +" statement is, and you need to invoke 'man sh'? +" +" Your problems are over now! +" +" Attached is a Vim script file for turning gvim into a shell script editor. +" It may also be used as an example how to use menus in Vim. +" +" Written by: Lennart Schultz + +imenu Stmts.for for in do doneki kk0elli +imenu Stmts.case case in ) ;; esacbki k0elli +imenu Stmts.if if then fiki kk0elli +imenu Stmts.if-else if then else fiki kki kk0elli +imenu Stmts.elif elif then ki kk0elli +imenu Stmts.while while do doneki kk0elli +imenu Stmts.break break +imenu Stmts.continue continue +imenu Stmts.function () { }ki k0i +imenu Stmts.return return +imenu Stmts.return-true return 0 +imenu Stmts.return-false return 1 +imenu Stmts.exit exit +imenu Stmts.shift shift +imenu Stmts.trap trap +imenu Test.existence [ -e ]hi +imenu Test.existence - file [ -f ]hi +imenu Test.existence - file (not empty) [ -s ]hi +imenu Test.existence - directory [ -d ]hi +imenu Test.existence - executable [ -x ]hi +imenu Test.existence - readable [ -r ]hi +imenu Test.existence - writable [ -w ]hi +imenu Test.String is empty [ x = "x$" ]hhi +imenu Test.String is not empty [ x != "x$" ]hhi +imenu Test.Strings is equal [ "" = "" ]hhhhhhhi +imenu Test.Strings is not equal [ "" != "" ]hhhhhhhhi +imenu Test.Values is greater than [ -gt ]hhhhhhi +imenu Test.Values is greater equal [ -ge ]hhhhhhi +imenu Test.Values is equal [ -eq ]hhhhhhi +imenu Test.Values is not equal [ -ne ]hhhhhhi +imenu Test.Values is less than [ -lt ]hhhhhhi +imenu Test.Values is less equal [ -le ]hhhhhhi +imenu ParmSub.Substitute word if parm not set ${:-}hhi +imenu ParmSub.Set parm to word if not set ${:=}hhi +imenu ParmSub.Substitute word if parm set else nothing ${:+}hhi +imenu ParmSub.If parm not set print word and exit ${:?}hhi +imenu SpShVars.Number of positional parameters ${#} +imenu SpShVars.All positional parameters (quoted spaces) ${*} +imenu SpShVars.All positional parameters (unquoted spaces) ${@} +imenu SpShVars.Flags set ${-} +imenu SpShVars.Return code of last command ${?} +imenu SpShVars.Process number of this shell ${$} +imenu SpShVars.Process number of last background command ${!} +imenu Environ.HOME ${HOME} +imenu Environ.PATH ${PATH} +imenu Environ.CDPATH ${CDPATH} +imenu Environ.MAIL ${MAIL} +imenu Environ.MAILCHECK ${MAILCHECK} +imenu Environ.PS1 ${PS1} +imenu Environ.PS2 ${PS2} +imenu Environ.IFS ${IFS} +imenu Environ.SHACCT ${SHACCT} +imenu Environ.SHELL ${SHELL} +imenu Environ.LC_CTYPE ${LC_CTYPE} +imenu Environ.LC_MESSAGES ${LC_MESSAGES} +imenu Builtins.cd cd +imenu Builtins.echo echo +imenu Builtins.eval eval +imenu Builtins.exec exec +imenu Builtins.export export +imenu Builtins.getopts getopts +imenu Builtins.hash hash +imenu Builtins.newgrp newgrp +imenu Builtins.pwd pwd +imenu Builtins.read read +imenu Builtins.readonly readonly +imenu Builtins.return return +imenu Builtins.times times +imenu Builtins.type type +imenu Builtins.umask umask +imenu Builtins.wait wait +imenu Set.set set +imenu Set.unset unset +imenu Set.mark modified or modified variables set -a +imenu Set.exit when command returns non-zero exit code set -e +imenu Set.Disable file name generation set -f +imenu Set.remember function commands set -h +imenu Set.All keyword arguments are placed in the environment set -k +imenu Set.Read commands but do not execute them set -n +imenu Set.Exit after reading and executing one command set -t +imenu Set.Treat unset variables as an error when substituting set -u +imenu Set.Print shell input lines as they are read set -v +imenu Set.Print commands and their arguments as they are executed set -x diff --git a/src/version.c b/src/version.c index 70a5969a93..a009d8cf83 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1676, /**/ 1675, /**/ From 0b9e4d1224522791c0dbbd45742cbd688be823f3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:05:47 +0200 Subject: [PATCH 12/18] patch 7.4.1677 Problem: A reference to the removed file_select plugin remains. Solution: Remove it. --- runtime/macros/README.txt | 18 +++-- runtime/macros/editexisting.vim | 122 +------------------------------- src/version.c | 2 + 3 files changed, 13 insertions(+), 129 deletions(-) diff --git a/runtime/macros/README.txt b/runtime/macros/README.txt index 01635460d4..22f9a97442 100644 --- a/runtime/macros/README.txt +++ b/runtime/macros/README.txt @@ -8,28 +8,26 @@ maze Macros that solve a maze (amazing!). urm Macros that simulate a simple computer: "Universal Register Machine" + The other files contain some handy utilities. They also serve as examples for how to use Vi and Vim functionality. less.sh + less.vim make Vim work like less (or more) -This one is only for Unix. -file_select.vim macros that make a handy file selector - The following have been moved to an optional package. Add the command to your vimrc file to use the package: -packadd! dvorak Dvorak keyboard support; adds mappings +packadd! dvorak " Dvorak keyboard support; adds mappings -packadd! editexisting when editing a file that is already edited with - another Vim instance, go to that Vim instance +packadd! editexisting " when editing a file that is already edited with + " another Vim instance, go to that Vim instance -packadd! justify justifying text. +packadd! justify " justifying text. -packadd! matchit makes the % command work better +packadd! matchit " makes the % command work better -packadd! shellmenu menus for editing shell scripts in the GUI version +packadd! shellmenu " menus for editing shell scripts in the GUI version -packadd! swapmouse swap left and right mouse buttons +packadd! swapmouse " swap left and right mouse buttons diff --git a/runtime/macros/editexisting.vim b/runtime/macros/editexisting.vim index 3530e29dc4..6e8f74f22f 100644 --- a/runtime/macros/editexisting.vim +++ b/runtime/macros/editexisting.vim @@ -1,119 +1,3 @@ -" Vim Plugin: Edit the file with an existing Vim if possible -" Maintainer: Bram Moolenaar -" Last Change: 2014 Dec 06 - -" This is a plugin, drop it in your (Unix) ~/.vim/plugin or (Win32) -" $VIM/vimfiles/plugin directory. Or make a symbolic link, so that you -" automatically use the latest version. - -" This plugin serves two purposes: -" 1. On startup, if we were invoked with one file name argument and the file -" is not modified then try to find another Vim instance that is editing -" this file. If there is one then bring it to the foreground and exit. -" 2. When a file is edited and a swap file exists for it, try finding that -" other Vim and bring it to the foreground. Requires Vim 7, because it -" uses the SwapExists autocommand event. -if v:version < 700 - finish -endif - -" Function that finds the Vim instance that is editing "filename" and brings -" it to the foreground. -func s:EditElsewhere(filename) - let fname_esc = substitute(a:filename, "'", "''", "g") - - let servers = serverlist() - while servers != '' - " Get next server name in "servername"; remove it from "servers". - let i = match(servers, "\n") - if i == -1 - let servername = servers - let servers = '' - else - let servername = strpart(servers, 0, i) - let servers = strpart(servers, i + 1) - endif - - " Skip ourselves. - if servername ==? v:servername - continue - endif - - " Check if this server is editing our file. - if remote_expr(servername, "bufloaded('" . fname_esc . "')") - " Yes, bring it to the foreground. - if has("win32") - call remote_foreground(servername) - endif - call remote_expr(servername, "foreground()") - - if remote_expr(servername, "exists('*EditExisting')") - " Make sure the file is visible in a window (not hidden). - " If v:swapcommand exists and is set, send it to the server. - if exists("v:swapcommand") - let c = substitute(v:swapcommand, "'", "''", "g") - call remote_expr(servername, "EditExisting('" . fname_esc . "', '" . c . "')") - else - call remote_expr(servername, "EditExisting('" . fname_esc . "', '')") - endif - endif - - if !(has('vim_starting') && has('gui_running') && has('gui_win32')) - " Tell the user what is happening. Not when the GUI is starting - " though, it would result in a message box. - echomsg "File is being edited by " . servername - sleep 2 - endif - return 'q' - endif - endwhile - return '' -endfunc - -" When the plugin is loaded and there is one file name argument: Find another -" Vim server that is editing this file right now. -if argc() == 1 && !&modified - if s:EditElsewhere(expand("%:p")) == 'q' - quit - endif -endif - -" Setup for handling the situation that an existing swap file is found. -try - au! SwapExists * let v:swapchoice = s:EditElsewhere(expand(":p")) -catch - " Without SwapExists we don't do anything for ":edit" commands -endtry - -" Function used on the server to make the file visible and possibly execute a -" command. -func! EditExisting(fname, command) - " Get the window number of the file in the current tab page. - let winnr = bufwinnr(a:fname) - if winnr <= 0 - " Not found, look in other tab pages. - let bufnr = bufnr(a:fname) - for i in range(tabpagenr('$')) - if index(tabpagebuflist(i + 1), bufnr) >= 0 - " Make this tab page the current one and find the window number. - exe 'tabnext ' . (i + 1) - let winnr = bufwinnr(a:fname) - break - endif - endfor - endif - - if winnr > 0 - exe winnr . "wincmd w" - elseif exists('*fnameescape') - exe "split " . fnameescape(a:fname) - else - exe "split " . escape(a:fname, " \t\n*?[{`$\\%#'\"|!<") - endif - - if a:command != '' - exe "normal! " . a:command - endif - - redraw -endfunc +" Load the editexisting package. +" For those users who were loading the editexisting plugin from here. +packadd editexisting diff --git a/src/version.c b/src/version.c index a009d8cf83..878eb24944 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1677, /**/ 1676, /**/ From 8b29aba0192cc56294ef49bb3c01adff4b8f3a28 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:17:16 +0200 Subject: [PATCH 13/18] patch 7.4.1678 Problem: Warning for unused argument. Solution: Add UNUSED. (Dominique Pelle) --- src/if_mzsch.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/if_mzsch.c b/src/if_mzsch.c index a0c6483c1e..d255d4adf1 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -1073,7 +1073,7 @@ load_base_module(void *data) } static Scheme_Object * -load_base_module_on_error(void *data) +load_base_module_on_error(void *data UNUSED) { load_base_module_failed = TRUE; return scheme_null; diff --git a/src/version.c b/src/version.c index 878eb24944..ec283a19e2 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1678, /**/ 1677, /**/ From 7d2a5796d39905a972e8f74af5f7b0a62e3de173 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:30:50 +0200 Subject: [PATCH 14/18] patch 7.4.1679 Problem: Coverity: copying value of v_lock without initializing it. Solution: Init v_lock in rettv_list_alloc() and rettv_dict_alloc(). --- src/eval.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/eval.c b/src/eval.c index 2c093d4154..cd7ce25cd9 100644 --- a/src/eval.c +++ b/src/eval.c @@ -6027,6 +6027,7 @@ rettv_list_alloc(typval_T *rettv) rettv->vval.v_list = l; rettv->v_type = VAR_LIST; + rettv->v_lock = 0; ++l->lv_refcount; return OK; } @@ -7277,6 +7278,7 @@ rettv_dict_alloc(typval_T *rettv) rettv->vval.v_dict = d; rettv->v_type = VAR_DICT; + rettv->v_lock = 0; ++d->dv_refcount; return OK; } diff --git a/src/version.c b/src/version.c index ec283a19e2..e1f7a2adda 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1679, /**/ 1678, /**/ From 925ccfde79bf734bc89269c705cebe2d49fe6444 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:38:02 +0200 Subject: [PATCH 15/18] patch 7.4.1680 Problem: Coverity warns for not checking name length (false positive). Solution: Only copy the characters we know are there. --- src/channel.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/channel.c b/src/channel.c index ba9f9c736c..98bc6be63b 100644 --- a/src/channel.c +++ b/src/channel.c @@ -2284,11 +2284,11 @@ channel_status(channel_T *channel) channel_part_info(channel_T *channel, dict_T *dict, char *name, int part) { chanpart_T *chanpart = &channel->ch_part[part]; - char namebuf[20]; + char namebuf[20]; /* longest is "sock_timeout" */ size_t tail; char *s = ""; - STRCPY(namebuf, name); + vim_strncpy((char_u *)namebuf, (char_u *)name, 4); STRCAT(namebuf, "_"); tail = STRLEN(namebuf); diff --git a/src/version.c b/src/version.c index e1f7a2adda..4778bfecdc 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1680, /**/ 1679, /**/ From ef9d9b94a8803c405884bb6914ed745ede57c596 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:44:50 +0200 Subject: [PATCH 16/18] patch 7.4.1681 Problem: Coverity warns for fixed size buffer length (false positive). Solution: Add a check for the name length. --- src/eval.c | 5 +++++ src/version.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/eval.c b/src/eval.c index cd7ce25cd9..1516fe596c 100644 --- a/src/eval.c +++ b/src/eval.c @@ -933,6 +933,11 @@ eval_init(void) for (i = 0; i < VV_LEN; ++i) { p = &vimvars[i]; + if (STRLEN(p->vv_name) > 16) + { + EMSG("INTERNAL: name too long, increase size of dictitem16_T"); + getout(1); + } STRCPY(p->vv_di.di_key, p->vv_name); if (p->vv_flags & VV_RO) p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; diff --git a/src/version.c b/src/version.c index 4778bfecdc..26928e95b1 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1681, /**/ 1680, /**/ From 72188e9aae26e6191c68ff673ef145104b17c64f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 22:48:29 +0200 Subject: [PATCH 17/18] patch 7.4.1682 Problem: Coverity: no check for NULL. Solution: Add check for invalid argument to assert_match(). --- src/eval.c | 4 +++- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index 1516fe596c..0784215932 100644 --- a/src/eval.c +++ b/src/eval.c @@ -9580,7 +9580,9 @@ f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1); char_u *text = get_tv_string_buf_chk(&argvars[1], buf2); - if (!pattern_match(pat, text, FALSE)) + if (pat == NULL || text == NULL) + EMSG(_(e_invarg)); + else if (!pattern_match(pat, text, FALSE)) { prepare_assert_error(&ga); fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], diff --git a/src/version.c b/src/version.c index 26928e95b1..00e25e9014 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1682, /**/ 1681, /**/ From e609ad557c15e3e5d1e9ace2c578f48c5589c488 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 28 Mar 2016 23:05:48 +0200 Subject: [PATCH 18/18] =?UTF-8?q?patch=207.4.1683=20Problem:=20=20=20=20Ge?= =?UTF-8?q?nerated=20.bat=20files=20do=20not=20support=20--nofork.=20Solut?= =?UTF-8?q?ion:=20=20=20Add=20check=20for=20--nofork.=20=20Also=20add=20"s?= =?UTF-8?q?etlocal".=20(Kevin=20Cant=C3=BA,=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20closes=20#659)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dosinst.c | 4 ++++ src/version.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/dosinst.c b/src/dosinst.c index 5b54380fe7..809789fb7f 100644 --- a/src/dosinst.c +++ b/src/dosinst.c @@ -762,6 +762,7 @@ install_bat_choice(int idx) fprintf(fd, "@echo off\n"); fprintf(fd, "rem -- Run Vim --\n"); fprintf(fd, "\n"); + fprintf(fd, "setlocal\n"); /* Don't use double quotes for the "set" argument, also when it * contains a space. The quotes would be included in the value @@ -793,6 +794,9 @@ install_bat_choice(int idx) fprintf(fd, "if .%%1==. goto loopend\n"); if (*exename == 'g') { + fprintf(fd, "if NOT .%%1==.--nofork goto noforklongarg\n"); + fprintf(fd, "set VIMNOFORK=1\n"); + fprintf(fd, ":noforklongarg\n"); fprintf(fd, "if NOT .%%1==.-f goto noforkarg\n"); fprintf(fd, "set VIMNOFORK=1\n"); fprintf(fd, ":noforkarg\n"); diff --git a/src/version.c b/src/version.c index 00e25e9014..333c0d8145 100644 --- a/src/version.c +++ b/src/version.c @@ -748,6 +748,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1683, /**/ 1682, /**/