commit d235b1d261ae9f275ac1f412dd8a8ad3f1c45e51 (HEAD, refs/remotes/origin/master) Author: Daniel Colascione Date: Mon Mar 23 01:38:12 2015 -0700 Try to avoid fontifying macros in funcall position * lisp/emacs-lisp/lisp-mode.el (lisp--el-non-funcall-position-p): New function. (lisp--el-match-keyword): Use it. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8f1534a..630265a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2015-03-23 Daniel Colascione + + * emacs-lisp/lisp-mode.el (lisp--el-non-funcall-position-p): New function. + (lisp--el-match-keyword): Use it. + 2015-03-23 Daiki Ueno * subr.el (start-process): New function, ported from the C diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 9c41945..52bc6a5 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -181,13 +181,47 @@ nil))) res)) +(defun lisp--el-non-funcall-position-p (&optional pos) + "Heuristically determine whether POS is an evaluated position." + (setf pos (or pos (point))) + (save-match-data + (save-excursion + (goto-char pos) + (or (eql (char-before) ?\') + (let ((parent + (ignore-errors + (up-list -1) + (cond + ((looking-at (rx "(" (* (syntax -)) "(")) + (up-list -1) + (when (looking-at "(\\_") + (goto-char (match-end 0)) + 'let)) + ((looking-at + (rx "(" + (group-n 1 (+ (or (syntax w) (syntax _)))) + symbol-end)) + (prog1 (intern-soft (match-string-no-properties 1)) + (goto-char (match-end 1)))))))) + (or (eq parent 'declare) + (and (eq parent 'let) + (progn + (forward-sexp 1) + (< pos (point)))) + (and (eq parent 'condition-case) + (progn + (forward-sexp 2) + (< (point) pos))))))))) + (defun lisp--el-match-keyword (limit) (catch 'found (while (re-search-forward "(\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>" limit t) (let ((sym (intern-soft (match-string 1)))) (when (or (special-form-p sym) (and (macrop sym) - (not (get sym 'no-font-lock-keyword)))) + (not (get sym 'no-font-lock-keyword)) + (not (lisp--el-non-funcall-position-p + (match-beginning 0))))) (throw 'found t)))))) (defun lisp--el-font-lock-flush-elisp-buffers (&optional file) commit 47e0e319329a1ecf9da4fa1afd2b9f2738fada67 Author: Daiki Ueno Date: Mon Mar 23 12:40:29 2015 +0900 Generalize start-process with keyword args * src/process.c (Fmake_process): New function. (create_process, create_pty): Check p->pty_flag instead of Vprocess_connection_type. (syms_of_process): Register QCcommand, QCconnection_type, Qpty, Qpipe, and Smake_process. Unregister Sstart_process. * lisp/subr.el (start-process): New function, ported from the C implementation. * doc/lispref/processes.texi (Asynchronous Processes): Mention `make-process'. * etc/NEWS: Mention `make-process'. diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 3644d40..ff1f814 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,7 @@ +2015-03-23 Daiki Ueno + + * processes.texi (Asynchronous Processes): Mention `make-process'. + 2015-03-18 Eli Zaretskii * minibuf.texi (Basic Completion): Fix a typo. (Bug#20108) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 177cd68..3e9cc50 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -692,6 +692,61 @@ use the function @code{process-tty-name} (@pxref{Process Information}). @end defvar +@defun make-process &rest args +This function is like @code{start-process}, but takes keyword arguments. + +The arguments @var{args} are a list of keyword/argument pairs. +Omitting a keyword is always equivalent to specifying it with value +@code{nil}. Here are the meaningful keywords: + +@table @asis +@item :name @var{name} +Use the string @var{name} as the process name. It is modified if +necessary to make it unique. + +@item :buffer @var{buffer} +Use @var{buffer} as the process buffer. + +@item :command @var{command} +Use @var{command} as the command line of the process. @var{command} +is a list starting with the program's executable file name, followed +by strings to give to program as arguments. + +@item :coding @var{coding} +If @var{coding} is a symbol, it specifies the coding system to be +used for both reading and writing of data from and to the +connection. If @var{coding} is a cons cell +@w{@code{(@var{decoding} . @var{encoding})}}, then @var{decoding} +will be used for reading and @var{encoding} for writing. + +If @var{coding} is @code{nil}, the default rules for finding the +coding system will apply. @xref{Default Coding Systems}. + +@item :connection-type @var{TYPE} +Initialize the type of device used to communicate with the subprocess. +Possible values are @code{pty} to use a pty, @code{pipe} to use a +pipe, or @code{nil} to use the default derived from the value of +the @code{process-connection-type} variable. + +@item :noquery @var{query-flag} +Initialize the process query flag to @var{query-flag}. +@xref{Query Before Exit}. + +@item :stop @var{stopped} +If @var{stopped} is non-@code{nil}, start the process in the +``stopped'' state. + +@item :filter @var{filter} +Initialize the process filter to @var{filter}. + +@item :sentinel @var{sentinel} +Initialize the process sentinel to @var{sentinel}. +@end table + +The original argument list, modified with the actual connection +information, is available via the @code{process-contact} function. +@end defun + @node Deleting Processes @section Deleting Processes @cindex deleting processes diff --git a/etc/ChangeLog b/etc/ChangeLog index c94e122..e146f78 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,7 @@ +2015-03-23 Daiki Ueno + + * NEWS: Mention `make-process'. + 2015-03-21 Titus von der Malsburg * NEWS: Mention `default-font-width', `window-font-height', diff --git a/etc/NEWS b/etc/NEWS index 7cdb24b..3b848dc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -651,6 +651,11 @@ word syntax, use `\sw' instead. * Lisp Changes in Emacs 25.1 +** New function `make-process' provides an alternative interface to +`start-process'. It allows programs to set process parameters such as +process filter, sentinel, etc., through keyword arguments (similar to +`make-network-process'). + ** `read-buffer' takes a new `predicate' argument. ** Emacs Lisp now supports generators. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 596b6e2..8f1534a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2015-03-23 Daiki Ueno + + * subr.el (start-process): New function, ported from the C + implementation. + 2015-03-23 Daniel Colascione Automatically adjust process window sizes. diff --git a/lisp/subr.el b/lisp/subr.el index deadca6..163a1c4 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1901,6 +1901,30 @@ and the file name is displayed in the echo area." ;;;; Process stuff. +(defun start-process (name buffer program &rest program-args) + "Start a program in a subprocess. Return the process object for it. +NAME is name for process. It is modified if necessary to make it unique. +BUFFER is the buffer (or buffer name) to associate with the process. + +Process output (both standard output and standard error streams) goes +at end of BUFFER, unless you specify an output stream or filter +function to handle the output. BUFFER may also be nil, meaning that +this process is not associated with any buffer. + +PROGRAM is the program file name. It is searched for in `exec-path' +\(which see). If nil, just associate a pty with the buffer. Remaining +arguments are strings to give program as arguments. + +If you want to separate standard output from standard error, invoke +the command through a shell and redirect one of them using the shell +syntax." + (unless (fboundp 'make-process) + (error "Emacs was compiled without subprocess support")) + (apply #'make-process + (append (list :name name :buffer buffer) + (if program + (list :command (cons program program-args)))))) + (defun process-lines (program &rest args) "Execute PROGRAM with ARGS, returning its output as a list of lines. Signal an error if the program returns with a non-zero exit status." diff --git a/src/ChangeLog b/src/ChangeLog index 79feb61..6c7955a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2015-03-23 Daiki Ueno + + * process.c (Fmake_process): New function. + (create_process, create_pty): Check p->pty_flag instead of + Vprocess_connection_type. + (syms_of_process): Register QCcommand, QCconnection_type, Qpty, + Qpipe, and Smake_process. Unregister Sstart_process. + 2015-03-22 Jan Djärv * fontset.c (fontset_pattern_regexp): Replace + 1 with + 3 for diff --git a/src/process.c b/src/process.c index 1d935ba..5abe748 100644 --- a/src/process.c +++ b/src/process.c @@ -1355,34 +1355,63 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0, static void start_process_unwind (Lisp_Object proc); -DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0, +DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0, doc: /* Start a program in a subprocess. Return the process object for it. -NAME is name for process. It is modified if necessary to make it unique. -BUFFER is the buffer (or buffer name) to associate with the process. -Process output (both standard output and standard error streams) goes -at end of BUFFER, unless you specify an output stream or filter -function to handle the output. BUFFER may also be nil, meaning that -this process is not associated with any buffer. +This is similar to `start-process', but arguments are specified as +keyword/argument pairs. The following arguments are defined: -PROGRAM is the program file name. It is searched for in `exec-path' -(which see). If nil, just associate a pty with the buffer. Remaining -arguments are strings to give program as arguments. +:name NAME -- NAME is name for process. It is modified if necessary +to make it unique. + +:buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate +with the process. Process output goes at end of that buffer, unless +you specify an output stream or filter function to handle the output. +BUFFER may be also nil, meaning that this process is not associated +with any buffer. -If you want to separate standard output from standard error, invoke -the command through a shell and redirect one of them using the shell -syntax. +:command COMMAND -- COMMAND is a list starting with the program file +name, followed by strings to give to the program as arguments. + +:coding CODING -- If CODING is a symbol, it specifies the coding +system used for both reading and writing for this process. If CODING +is a cons (DECODING . ENCODING), DECODING is used for reading, and +ENCODING is used for writing. + +:noquery BOOL -- When exiting Emacs, query the user if BOOL is nil and +the process is running. If BOOL is not given, query before exiting. -usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) +:stop BOOL -- Start process in the `stopped' state if BOOL non-nil. +In the stopped state, a process does not accept incoming data, but you +can send outgoing data. The stopped state is cleared by +`continue-process' and set by `stop-process'. + +:connection-type TYPE -- TYPE is control type of device used to +communicate with subprocesses. Values are `pipe' to use a pipe, `pty' +to use a pty, or nil to use the default specified through +`process-connection-type'. + +:filter FILTER -- Install FILTER as the process filter. + +:sentinel SENTINEL -- Install SENTINEL as the process sentinel. + +usage: (make-process &rest ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object buffer, name, program, proc, current_dir, tem; - unsigned char **new_argv; + Lisp_Object buffer, name, command, program, proc, contact, current_dir, tem; ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); + struct gcpro gcpro1; USE_SAFE_ALLOCA; - buffer = args[1]; + if (nargs == 0) + return Qnil; + + /* Save arguments for process-contact and clone-process. */ + contact = Flist (nargs, args); + GCPRO1 (contact); + + buffer = Fplist_get (contact, QCbuffer); if (!NILP (buffer)) buffer = Fget_buffer_create (buffer); @@ -1402,10 +1431,14 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) UNGCPRO; } - name = args[0]; + name = Fplist_get (contact, QCname); CHECK_STRING (name); - program = args[2]; + command = Fplist_get (contact, QCcommand); + if (CONSP (command)) + program = XCAR (command); + else + program = Qnil; if (!NILP (program)) CHECK_STRING (program); @@ -1423,7 +1456,22 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) pset_buffer (XPROCESS (proc), buffer); pset_sentinel (XPROCESS (proc), Qinternal_default_process_sentinel); pset_filter (XPROCESS (proc), Qinternal_default_process_filter); - pset_command (XPROCESS (proc), Flist (nargs - 2, args + 2)); + pset_command (XPROCESS (proc), Fcopy_sequence (command)); + + if (tem = Fplist_get (contact, QCnoquery), !NILP (tem)) + XPROCESS (proc)->kill_without_query = 1; + if (tem = Fplist_get (contact, QCstop), !NILP (tem)) + pset_command (XPROCESS (proc), Qt); + + tem = Fplist_get (contact, QCconnection_type); + if (EQ (tem, Qpty)) + XPROCESS (proc)->pty_flag = true; + else if (EQ (tem, Qpipe)) + XPROCESS (proc)->pty_flag = false; + else if (NILP (tem)) + XPROCESS (proc)->pty_flag = !NILP (Vprocess_connection_type); + else + report_file_error ("Unknown connection type", tem); #ifdef HAVE_GNUTLS /* AKA GNUTLS_INITSTAGE(proc). */ @@ -1453,15 +1501,29 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) Lisp_Object val, *args2; struct gcpro gcpro1, gcpro2; - val = Vcoding_system_for_read; + tem = Fplist_get (contact, QCcoding); + if (!NILP (tem)) + { + val = tem; + if (CONSP (val)) + val = XCAR (val); + } + else + val = Vcoding_system_for_read; if (NILP (val)) { - SAFE_ALLOCA_LISP (args2, nargs + 1); - args2[0] = Qstart_process; - for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; + ptrdiff_t nargs2 = 3 + XINT (Flength (command)); + Lisp_Object tem2; + SAFE_ALLOCA_LISP (args2, nargs2); + i = 0; + args2[i++] = Qstart_process; + args2[i++] = name; + args2[i++] = buffer; + for (tem2 = command; CONSP (tem2); tem2 = XCDR (tem2)) + args2[i++] = XCAR (tem2); GCPRO2 (proc, current_dir); if (!NILP (program)) - coding_systems = Ffind_operation_coding_system (nargs + 1, args2); + coding_systems = Ffind_operation_coding_system (nargs2, args2); UNGCPRO; if (CONSP (coding_systems)) val = XCAR (coding_systems); @@ -1470,17 +1532,30 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) } pset_decode_coding_system (XPROCESS (proc), val); - val = Vcoding_system_for_write; + if (!NILP (tem)) + { + val = tem; + if (CONSP (val)) + val = XCDR (val); + } + else + val = Vcoding_system_for_write; if (NILP (val)) { if (EQ (coding_systems, Qt)) { - SAFE_ALLOCA_LISP (args2, nargs + 1); - args2[0] = Qstart_process; - for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; + ptrdiff_t nargs2 = 3 + XINT (Flength (command)); + Lisp_Object tem2; + SAFE_ALLOCA_LISP (args2, nargs2); + i = 0; + args2[i++] = Qstart_process; + args2[i++] = name; + args2[i++] = buffer; + for (tem2 = command; CONSP (tem2); tem2 = XCDR (tem2)) + args2[i++] = XCAR (tem2); GCPRO2 (proc, current_dir); if (!NILP (program)) - coding_systems = Ffind_operation_coding_system (nargs + 1, args2); + coding_systems = Ffind_operation_coding_system (nargs2, args2); UNGCPRO; } if (CONSP (coding_systems)) @@ -1506,16 +1581,20 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) if (!NILP (program)) { + Lisp_Object program_args = XCDR (command); + unsigned char **new_argv; + ptrdiff_t new_argc; + /* If program file name is not absolute, search our path for it. Put the name we will really use in TEM. */ if (!IS_DIRECTORY_SEP (SREF (program, 0)) && !(SCHARS (program) > 1 && IS_DEVICE_SEP (SREF (program, 1)))) { - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + struct gcpro gcpro1, gcpro2; tem = Qnil; - GCPRO4 (name, program, buffer, current_dir); + GCPRO2 (buffer, current_dir); openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK), false); UNGCPRO; @@ -1534,7 +1613,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) tem = remove_slash_colon (tem); { - Lisp_Object arg_encoding = Qnil; + Lisp_Object arg_encoding = Qnil, tem2; struct gcpro gcpro1; GCPRO1 (tem); @@ -1547,9 +1626,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) systems for encoding arguments and for encoding data sent to the process. */ - for (i = 3; i < nargs; i++) + for (tem2 = program_args; CONSP (tem2); tem2 = XCDR (tem2)) { - tem = Fcons (args[i], tem); + tem = Fcons (XCAR (tem2), tem); CHECK_STRING (XCAR (tem)); if (STRING_MULTIBYTE (XCAR (tem))) { @@ -1567,10 +1646,11 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) /* Now that everything is encoded we can collect the strings into NEW_ARGV. */ - SAFE_NALLOCA (new_argv, 1, nargs - 1); - new_argv[nargs - 2] = 0; + new_argc = XINT (Flength (tem)); + SAFE_NALLOCA (new_argv, 1, new_argc + 1); + new_argv[new_argc] = 0; - for (i = nargs - 2; i-- != 0; ) + for (i = new_argc - 1; i >= 0; i--) { new_argv[i] = SDATA (XCAR (tem)); tem = XCDR (tem); @@ -1581,6 +1661,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) else create_pty (proc); + UNGCPRO; SAFE_FREE (); return unbind_to (count, proc); } @@ -1648,7 +1729,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) inchannel = outchannel = -1; - if (!NILP (Vprocess_connection_type)) + if (p->pty_flag) outchannel = inchannel = allocate_pty (pty_name); if (inchannel >= 0) @@ -1701,8 +1782,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) p->pty_flag = pty_flag; pset_status (p, Qrun); - FD_SET (inchannel, &input_wait_mask); - FD_SET (inchannel, &non_keyboard_wait_mask); + if (!EQ (p->command, Qt)) + { + FD_SET (inchannel, &input_wait_mask); + FD_SET (inchannel, &non_keyboard_wait_mask); + } + if (inchannel > max_process_desc) max_process_desc = inchannel; @@ -1894,7 +1979,7 @@ create_pty (Lisp_Object process) { struct Lisp_Process *p = XPROCESS (process); char pty_name[PTY_NAME_SIZE]; - int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name); + int pty_fd = !p->pty_flag ? -1 : allocate_pty (pty_name); if (pty_fd >= 0) { @@ -7269,6 +7354,10 @@ syms_of_process (void) DEFSYM (QCstop, ":stop"); DEFSYM (QCoptions, ":options"); DEFSYM (QCplist, ":plist"); + DEFSYM (QCcommand, ":command"); + DEFSYM (QCconnection_type, ":connection-type"); + DEFSYM (Qpty, "pty"); + DEFSYM (Qpipe, "pipe"); DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event"); @@ -7371,7 +7460,7 @@ The variable takes effect when `start-process' is called. */); defsubr (&Sprocess_plist); defsubr (&Sset_process_plist); defsubr (&Sprocess_list); - defsubr (&Sstart_process); + defsubr (&Smake_process); defsubr (&Sserial_process_configure); defsubr (&Smake_serial_process); defsubr (&Sset_network_process_option); commit 165bea78008ec7545698f2e893821b4090f20c79 Author: Daniel Colascione Date: Sun Mar 22 21:09:21 2015 -0700 Automatically adjust process window sizes * lisp/window.el (window-adjust-process-window-size-function): New customizable variable. (window-adjust-process-window-size) (window-adjust-process-window-size-smallest) (window-adjust-process-window-size-largest) (window--process-window-list, window--adjust-process-windows): New functions. (window-configuration-change-hook): Add `window--adjust-process-windows'. * lisp/term.el (term-mode): Observe result of `window-adjust-process-window-size-function'. (term-check-size): Delete. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1b8a4d3..596b6e2 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,20 @@ +2015-03-23 Daniel Colascione + + Automatically adjust process window sizes. + + * window.el (window-adjust-process-window-size-function): New + customizable variable. + (window-adjust-process-window-size) + (window-adjust-process-window-size-smallest) + (window-adjust-process-window-size-largest) + (window--process-window-list, window--adjust-process-windows): + New functions. + (window-configuration-change-hook): Add + `window--adjust-process-windows'. + * term.el (term-mode): Observe result of + `window-adjust-process-window-size-function'. + (term-check-size): Delete. + 2015-03-22 Jackson Ray Hamilton * textmodes/sgml-mode.el (sgml-attribute-offset): New defcustom. diff --git a/lisp/term.el b/lisp/term.el index a629af9..43138fa 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1145,7 +1145,7 @@ Entry to this mode runs the hooks on `term-mode-hook'." (make-local-variable 'term-scroll-show-maximum-output) (make-local-variable 'term-ptyp) (make-local-variable 'term-exec-hook) - (make-local-variable 'term-vertical-motion) + (set (make-local-variable 'term-vertical-motion) 'vertical-motion) (set (make-local-variable 'term-pending-delete-marker) (make-marker)) (make-local-variable 'term-current-face) (term-ansi-reset) @@ -1155,6 +1155,13 @@ Entry to this mode runs the hooks on `term-mode-hook'." (set (make-local-variable 'font-lock-defaults) '(nil t)) + (add-function :filter-return + (local 'window-adjust-process-window-size-function) + (lambda (size) + (when size + (term-reset-size (cdr size) (car size))) + size)) + (easy-menu-add term-terminal-menu) (easy-menu-add term-signals-menu) (or term-input-ring @@ -1197,12 +1204,6 @@ Entry to this mode runs the hooks on `term-mode-hook'." (goto-char save-point))) found)) -(defun term-check-size (process) - (when (or (/= term-height (window-text-height)) - (/= term-width (term-window-width))) - (term-reset-size (window-text-height) (term-window-width)) - (set-process-window-size process term-height term-width))) - (defun term-send-raw-string (chars) (deactivate-mark) (let ((proc (get-buffer-process (current-buffer)))) @@ -2772,15 +2773,11 @@ See `term-prompt-regexp'." (when (/= (point) (process-mark proc)) (setq save-point (point-marker))) - ;; Note if the window size has changed. We used to reset - ;; point too, but that gives incorrect results (Bug#4635). - (if (eq (window-buffer) (current-buffer)) - (progn - (setq term-vertical-motion (symbol-function 'vertical-motion)) - (term-check-size proc)) - (setq term-vertical-motion - (symbol-function 'term-buffer-vertical-motion))) - (setq save-marker (copy-marker (process-mark proc))) + (setf term-vertical-motion + (if (eq (window-buffer) (current-buffer)) + 'vertical-motion + 'term-buffer-vertical-motion)) + (setq save-marker (copy-marker (process-mark proc))) (goto-char (process-mark proc)) (save-restriction @@ -3082,9 +3079,7 @@ See `term-prompt-regexp'." (eq (window-buffer selected) (current-buffer))) (term-display-line (car term-pending-frame) (cdr term-pending-frame)) - (setq term-pending-frame nil) - ;; We have created a new window, so check the window size. - (term-check-size proc)) + (setq term-pending-frame nil)) ;; Scroll each window displaying the buffer but (by default) ;; only if the point matches the process-mark we started with. diff --git a/lisp/window.el b/lisp/window.el index d176050..94fe521 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8029,7 +8029,107 @@ Otherwise, consult the value of `truncate-partial-width-windows' (window-buffer window)))) (if (integerp t-p-w-w) (< (window-width window) t-p-w-w) - t-p-w-w)))) + t-p-w-w)))) + + +;; Automatically inform subprocesses of changes to window size. + +(defcustom window-adjust-process-window-size-function + 'window-adjust-process-window-size-smallest + "Control how Emacs chooses inferior process window sizes. +Emacs uses this function to tell processes the space they have +available for displaying their output. After each window +configuration change, Emacs calls the value of +`window-adjust-process-window-size-function' for each process +with a buffer being displayed in at least one window. +This function is responsible for combining the sizes of the +displayed windows and returning a cons (WIDTH . HEIGHT) +describing the width and height with which Emacs will call +`set-process-window-size' for that process. If the function +returns `nil', Emacs does not call `set-process-window-size'. + +This function is called with the process buffer as the current +buffer and with two arguments: the process and a list of windows +displaying process. Modes can make this variable buffer-local; +additionally, the `adjust-window-size-function' process property +overrides the global or buffer-local value of +`window-adjust-process-window-size-function'." + :type '(choice + (const :tag "Minimum area of any window" + window-adjust-process-window-size-smallest) + (const :tag "Maximum area of any window" + window-adjust-process-window-size-largest) + (const :tag "Do not adjust process window sizes" ignore) + function) + :group 'windows + :version "25.1") + +(defun window-adjust-process-window-size (reducer process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. REDUCER is +a two-argument function used to combine the widths and heights of +the given windows." + (when windows + (let ((width (window-body-width (car windows))) + (height (window-body-height (car windows)))) + (dolist (window (cdr windows)) + (setf width (funcall reducer width (window-body-width window))) + (setf height (funcall reducer height (window-body-height window)))) + (cons width height)))) + +(defun window-adjust-process-window-size-smallest (process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. Choose the +smallest area availabe for displaying PROCESS's output." + (window-adjust-process-window-size #'min process windows)) + +(defun window-adjust-process-window-size-largest (process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. Choose the +largest area availabe for displaying PROCESS's output." + (window-adjust-process-window-size #'max process windows)) + +(defun window--process-window-list () + "Return an alist mapping processes to associated windows. +A window is associated with a process if that window is +displaying that processes's buffer." + (let ((processes (process-list)) + (process-windows nil)) + (walk-windows + (lambda (window) + (let ((buffer (window-buffer window)) + (iter processes)) + (while (let ((process (car iter))) + (if (and (process-live-p process) + (eq buffer (process-buffer process))) + (let ((procwin (assq process process-windows))) + ;; Add this window to the list of windows + ;; displaying process. + (if procwin + (push window (cdr procwin)) + (push (list process window) process-windows)) + ;; We found our process for this window, so + ;; stop iterating over the process list. + nil) + (setf iter (cdr iter))))))) + 1 t) + process-windows)) + +(defun window--adjust-process-windows () + "Update process window sizes to match the current window configuration." + (dolist (procwin (window--process-window-list)) + (let ((process (car procwin))) + (with-demoted-errors "Error adjusting window size: %S" + (with-current-buffer (process-buffer process) + (let ((size (funcall + (or (process-get process 'adjust-window-size-function) + window-adjust-process-window-size-function) + process (cdr procwin)))) + (when size + (set-process-window-size process (cdr size) (car size))))))))) + +(add-hook 'window-configuration-change-hook 'window--adjust-process-windows) + ;; Some of these are in tutorial--default-keys, so update that if you ;; change these. commit f4c23f458367769ba9a701792fa5720e58827fb4 Author: Jackson Ray Hamilton Date: Sun Mar 22 08:22:29 2015 -0700 Have `sgml-attribute-offset' control SGML attribute indentation Fixes: debbugs:20161 * textmodes/sgml-mode.el (sgml-attribute-offset): New defcustom. (sgml-calculate-indent): Use `sgml-attribute-offset' for attribute indentation. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 2fc318a..1b8a4d3 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,9 @@ +2015-03-22 Jackson Ray Hamilton + + * textmodes/sgml-mode.el (sgml-attribute-offset): New defcustom. + (sgml-calculate-indent): Use `sgml-attribute-offset' for attribute + indentation (bug#20161). + 2015-03-22 Dmitry Gutov * json.el (json-decode-char0): Delete this alias. diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index 12d98c8..8266647 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -46,6 +46,25 @@ :type 'integer :group 'sgml) +(defcustom sgml-attribute-offset 0 + "Specifies a delta for attribute indentation in `sgml-indent-line'. + +When 0, attribute indentation looks like this: + + + + +When 2, attribute indentation looks like this: + + + " + :version "25.1" + :type 'integer + :safe 'integerp + :group 'sgml) + (defcustom sgml-xml-mode nil "When non-nil, tag insertion functions will be XML-compliant. It is set to be buffer-local when the file has @@ -1510,13 +1529,13 @@ LCON is the lexical context, if any." (`pi nil) (`tag - (goto-char (1+ (cdr lcon))) + (goto-char (+ (cdr lcon) sgml-attribute-offset)) (skip-chars-forward "^ \t\n") ;Skip tag name. (skip-chars-forward " \t") (if (not (eolp)) (current-column) ;; This is the first attribute: indent. - (goto-char (1+ (cdr lcon))) + (goto-char (+ (cdr lcon) sgml-attribute-offset)) (+ (current-column) sgml-basic-offset))) (`text diff --git a/test/indent/sgml-mode-attribute.html b/test/indent/sgml-mode-attribute.html new file mode 100644 index 0000000..4cbec0a --- /dev/null +++ b/test/indent/sgml-mode-attribute.html @@ -0,0 +1,14 @@ + + + + + + + + commit 70a8bbe4437abe9166ba5522437c70791869fc95 Author: Glenn Morris Date: Sun Mar 22 16:50:00 2015 -0700 json-tests.el: Fix copyright diff --git a/test/automated/json-tests.el b/test/automated/json-tests.el index 378472e..881c237 100644 --- a/test/automated/json-tests.el +++ b/test/automated/json-tests.el @@ -1,6 +1,6 @@ ;;; json-tests.el --- Test suite for json.el -;; Copyright (C) 2015 Dmitry Gutov +;; Copyright (C) 2015 Free Software Foundation, Inc. ;; Author: Dmitry Gutov commit 127377c7113d1f01bafbb09b6d6730e9d8e5ac2e Author: Dmitry Gutov Date: Mon Mar 23 00:52:07 2015 +0200 Add a few tests for jsone.el * test/automated/json-tests.el: New file. diff --git a/test/ChangeLog b/test/ChangeLog index 15408a3..b12e9c0 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2015-03-22 Dmitry Gutov + + * automated/json-tests.el: New file. + 2015-03-19 Stefan Monnier * automated/eieio-tests.el (eieio-test-17-virtual-slot): Don't use diff --git a/test/automated/json-tests.el b/test/automated/json-tests.el new file mode 100644 index 0000000..378472e --- /dev/null +++ b/test/automated/json-tests.el @@ -0,0 +1,46 @@ +;;; json-tests.el --- Test suite for json.el + +;; Copyright (C) 2015 Dmitry Gutov + +;; Author: Dmitry Gutov + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Code: + +(require 'ert) +(require 'json) + +(ert-deftest json-encode-simple-alist () + (should (equal (json-encode '((a . 1) + (b . 2))) + "{\"a\":1,\"b\":2}"))) + +(ert-deftest json-read-simple-alist () + (should (equal (json-read-from-string "{\"a\": 1, \"b\": 2}") + '((b . 2) + (a . 1))))) + +(ert-deftest json-encode-string-with-special-chars () + (should (equal (json-encode-string "a\n\fb") + "\"a\\n\\fb\"")) + (should (equal (json-encode-string "\nasdфывfgh\t") + "\"\\nasd\\u0444\\u044b\\u0432fgh\\t\""))) + +(ert-deftest json-read-string-with-special-chars () + (should (equal (json-read-from-string "\"\\nasd\\u0444\\u044b\\u0432fgh\\t\"") + "\nasdфывfgh\t"))) + +(provide 'json-tests) +;;; json-tests.el ends here commit a3b6c249e9757761404c1f7a57de4217dcc2e583 Author: Dmitry Gutov Date: Mon Mar 23 00:50:58 2015 +0200 Rewrite json-encode-string Fixes: debbugs:20154 * lisp/json.el (json-decode-char0): Delete this alias. (json-encode-string): Rewrite to improve performance. (json-encode-char): Fold into `json-encode-string'. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 52c6a72..2fc318a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,9 @@ +2015-03-22 Dmitry Gutov + + * json.el (json-decode-char0): Delete this alias. + (json-encode-string): Rewrite to improve performance (bug#20154). + (json-encode-char): Fold into `json-encode-string'. + 2015-03-22 Artur Malabarba * menu-bar.el (menu-bar-update-buffers): Count displayed buffers diff --git a/lisp/json.el b/lisp/json.el index 98974e6..fb0f62c 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -55,7 +55,6 @@ ;; Compatibility code -(defalias 'json-encode-char0 'encode-char) (defalias 'json-decode-char0 'decode-char) @@ -313,24 +312,28 @@ representation will be parsed correctly." ;; String encoding -(defun json-encode-char (char) - "Encode CHAR as a JSON string." - (setq char (json-encode-char0 char 'ucs)) - (let ((control-char (car (rassoc char json-special-chars)))) - (cond - ;; Special JSON character (\n, \r, etc.). - (control-char - (format "\\%c" control-char)) - ;; ASCIIish printable character. - ((and (> char 31) (< char 127)) - (format "%c" char)) - ;; Fallback: UCS code point in \uNNNN form. - (t - (format "\\u%04x" char))))) - (defun json-encode-string (string) "Return a JSON representation of STRING." - (format "\"%s\"" (mapconcat 'json-encode-char string ""))) + ;; Reimplement the meat of `replace-regexp-in-string', for + ;; performance (bug#20154). + (let ((l (length string)) + (start 0) + res mb) + ;; Skip over ASCIIish printable characters. + (while (setq mb (string-match "[\"\\/\b\f\n\r\t]\\|[^ -~]" string start)) + (let* ((c (aref string mb)) + (special (rassq c json-special-chars))) + (push (substring string start mb) res) + (push (if special + ;; Special JSON character (\n, \r, etc.). + (string ?\\ (car special)) + ;; Fallback: UCS code point in \uNNNN form. + (format "\\u%04x" c)) + res) + (setq start (1+ mb)))) + (push (substring string start l) res) + (push "\"" res) + (apply #'concat "\"" (nreverse res)))) (defun json-encode-key (object) "Return a JSON representation of OBJECT. commit 2a954e8aa6917572cbf9431f7b1a9ae19be18d7c Author: Artur Malabarba Date: Sun Mar 22 19:29:57 2015 +0000 * menu-bar.el (menu-bar-update-buffers): Properly count buffers. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 2f9c430..52c6a72 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2015-03-22 Artur Malabarba + + * menu-bar.el (menu-bar-update-buffers): Count displayed buffers + for `buffers-menu-max-size', not total buffers. + 2015-03-21 Titus von der Malsburg * window.el (window-font-width, window-font-height) diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 5fdb937..2ace316 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -1949,20 +1949,20 @@ It must accept a buffer as its only required argument.") (let ((buffers (buffer-list)) (frames (frame-list)) buffers-menu) - ;; If requested, list only the N most recently selected buffers. - (if (and (integerp buffers-menu-max-size) - (> buffers-menu-max-size 1)) - (if (> (length buffers) buffers-menu-max-size) - (setcdr (nthcdr buffers-menu-max-size buffers) nil))) ;; Make the menu of buffers proper. (setq buffers-menu - (let (alist) + (let ((i 0) + (limit (if (and (integerp buffers-menu-max-size) + (> buffers-menu-max-size 1)) + buffers-menu-max-size most-positive-fixnum)) + alist) ;; Put into each element of buffer-list ;; the name for actual display, ;; perhaps truncated in the middle. - (dolist (buf buffers) - (let ((name (buffer-name buf))) + (while buffers + (let* ((buf (pop buffers)) + (name (buffer-name buf))) (unless (eq ?\s (aref name 0)) (push (menu-bar-update-buffers-1 (cons buf @@ -1976,7 +1976,11 @@ It must accept a buffer as its only required argument.") name (- (/ buffers-menu-buffer-name-length 2)))) name) )) - alist)))) + alist) + ;; If requested, list only the N most recently + ;; selected buffers. + (when (= limit (setq i (1+ i))) + (setq buffers nil))))) (list (menu-bar-buffer-vector alist)))) ;; Make a Frames menu if we have more than one frame. commit 32315502e0335f7840cdaa68d3fa3aa385a6943d Author: Jan D Date: Sun Mar 22 10:14:36 2015 +0100 Fixes: debbugs:20156 * src/fontset.c (fontset_pattern_regexp): Replace + 1 with + 3 for regexsize. diff --git a/src/ChangeLog b/src/ChangeLog index 5aa248e..79feb61 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2015-03-22 Jan Djärv + + * fontset.c (fontset_pattern_regexp): Replace + 1 with + 3 for + regexsize (Bug#20156). + 2015-03-21 Eli Zaretskii * emacs.c (synchronize_locale) [WINDOWSNT]: Ignore 'category' and diff --git a/src/fontset.c b/src/fontset.c index c0303fa..763d846 100644 --- a/src/fontset.c +++ b/src/fontset.c @@ -1074,7 +1074,7 @@ fontset_pattern_regexp (Lisp_Object pattern) expression matching. */ ptrdiff_t regexsize = (SBYTES (pattern) + (ndashes < 14 ? 2 : 5) * nstars - + 2 * nescs + 1); + + 2 * nescs + 3); USE_SAFE_ALLOCA; p1 = regex = SAFE_ALLOCA (regexsize);