electric.el 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. ;; electric -- Window maker and Command loop for `electric' modes.
  2. ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  3. ;; Principal author K. Shane Hartman
  4. ;; This file is part of GNU Emacs.
  5. ;; GNU Emacs is distributed in the hope that it will be useful,
  6. ;; but WITHOUT ANY WARRANTY. No author or distributor
  7. ;; accepts responsibility to anyone for the consequences of using it
  8. ;; or for whether it serves any particular purpose or works at all,
  9. ;; unless he says so in writing. Refer to the GNU Emacs General Public
  10. ;; License for full details.
  11. ;; Everyone is granted permission to copy, modify and redistribute
  12. ;; GNU Emacs, but only under the conditions described in the
  13. ;; GNU Emacs General Public License. A copy of this license is
  14. ;; supposed to have been given to you along with GNU Emacs so you
  15. ;; can know your rights and responsibilities. It should be in a
  16. ;; file named COPYING. Among other things, the copyright notice
  17. ;; and this notice must be preserved on all copies.
  18. (provide 'electric) ; zaaaaaaap
  19. ;; perhaps this should be in subr.el...
  20. (defun shrink-window-if-larger-than-buffer (window)
  21. (save-excursion
  22. (set-buffer (window-buffer window))
  23. (let ((w (selected-window)) ;save-window-excursion can't win
  24. (buffer-file-name buffer-file-name)
  25. (p (point))
  26. (n 0)
  27. (window-min-height 0)
  28. (buffer-read-only nil)
  29. (modified (buffer-modified-p)))
  30. (unwind-protect
  31. (progn
  32. (select-window window)
  33. (goto-char (point-min))
  34. (while (pos-visible-in-window-p (point-max))
  35. ;; defeat file locking... don't try this at home, kids!
  36. (setq buffer-file-name nil)
  37. (insert ?\n) (setq n (1+ n)))
  38. (if (> n 0) (shrink-window (1- n))))
  39. (delete-region (point-min) (point))
  40. (set-buffer-modified-p modified)
  41. (goto-char p)
  42. (select-window w)))))
  43. ;; This loop is the guts for non-standard modes which retain control
  44. ;; until some event occurs. It is a `do-forever', the only way out is to
  45. ;; throw. It assumes that you have set up the keymap, window, and
  46. ;; everything else: all it does is read commands and execute them -
  47. ;; providing error messages should one occur (if there is no loop
  48. ;; function - which see). The required argument is a tag which should
  49. ;; expect a value of nil if the user decides to punt. The
  50. ;; second argument is a prompt string (defaults to "->"). Given third
  51. ;; argument non-nil, it INHIBITS quitting unless the user types C-g at
  52. ;; toplevel. This is so user can do things like C-u C-g and not get
  53. ;; thrown out. Fourth argument, if non-nil, should be a function of two
  54. ;; arguments which is called after every command is executed. The fifth
  55. ;; argument, if provided, is the state variable for the function. If the
  56. ;; loop-function gets an error, the loop will abort WITHOUT throwing
  57. ;; (moral: use unwind-protect around call to this function for any
  58. ;; critical stuff). The second argument for the loop function is the
  59. ;; conditions for any error that occurred or nil if none.
  60. (defun Electric-command-loop (return-tag
  61. &optional prompt inhibit-quit
  62. loop-function loop-state)
  63. (if (not prompt) (setq prompt "->"))
  64. (let (cmd (err nil))
  65. (while t
  66. (setq cmd (read-key-sequence (if (stringp prompt)
  67. prompt (funcall prompt))))
  68. (setq last-command-char (aref cmd (1- (length cmd)))
  69. this-command (key-binding cmd)
  70. cmd this-command)
  71. (if (or (prog1 quit-flag (setq quit-flag nil))
  72. (= last-input-char ?\C-g))
  73. (progn (setq unread-command-char -1
  74. prefix-arg nil)
  75. ;; If it wasn't cancelling a prefix character, then quit.
  76. (if (or (= (length (this-command-keys)) 1)
  77. (not inhibit-quit)) ; safety
  78. (progn (ding)
  79. (message "Quit")
  80. (throw return-tag nil))
  81. (setq cmd nil))))
  82. (setq current-prefix-arg prefix-arg)
  83. (if cmd
  84. (condition-case conditions
  85. (progn (command-execute cmd)
  86. (if (or (prog1 quit-flag (setq quit-flag nil))
  87. (= last-input-char ?\C-g))
  88. (progn (setq unread-command-char -1)
  89. (if (not inhibit-quit)
  90. (progn (ding)
  91. (message "Quit")
  92. (throw return-tag nil))
  93. (ding)))))
  94. (buffer-read-only (if loop-function
  95. (setq err conditions)
  96. (ding)
  97. (message "Buffer is read-only")
  98. (sit-for 2)))
  99. (beginning-of-buffer (if loop-function
  100. (setq err conditions)
  101. (ding)
  102. (message "Beginning of Buffer")
  103. (sit-for 2)))
  104. (end-of-buffer (if loop-function
  105. (setq err conditions)
  106. (ding)
  107. (message "End of Buffer")
  108. (sit-for 2)))
  109. (error (if loop-function
  110. (setq err conditions)
  111. (ding)
  112. (message "Error: %s"
  113. (if (eq (car conditions) 'error)
  114. (car (cdr conditions))
  115. (prin1-to-string conditions)))
  116. (sit-for 2))))
  117. (ding))
  118. (if loop-function (funcall loop-function loop-state err))))
  119. (ding)
  120. (throw return-tag nil))
  121. ;; This function is like pop-to-buffer, sort of.
  122. ;; The algorithm is
  123. ;; If there is a window displaying buffer
  124. ;; Select it
  125. ;; Else if there is only one window
  126. ;; Split it, selecting the window on the bottom with height being
  127. ;; the lesser of max-height (if non-nil) and the number of lines in
  128. ;; the buffer to be displayed subject to window-min-height constraint.
  129. ;; Else
  130. ;; Switch to buffer in the current window.
  131. ;;
  132. ;; Then if max-height is nil, and not all of the lines in the buffer
  133. ;; are displayed, grab the whole screen.
  134. ;;
  135. ;; Returns selected window on buffer positioned at point-min.
  136. (defun Electric-pop-up-window (buffer &optional max-height)
  137. (let* ((win (or (get-buffer-window buffer) (selected-window)))
  138. (buf (get-buffer buffer))
  139. (one-window (one-window-p t))
  140. (pop-up-windows t)
  141. (target-height)
  142. (lines))
  143. (if (not buf)
  144. (error "Buffer %s does not exist" buffer)
  145. (save-excursion
  146. (set-buffer buf)
  147. (setq lines (count-lines (point-min) (point-max)))
  148. (setq target-height
  149. (min (max (if max-height (min max-height (1+ lines)) (1+ lines))
  150. window-min-height)
  151. (save-window-excursion
  152. (delete-other-windows)
  153. (1- (window-height (selected-window)))))))
  154. (cond ((and (eq (window-buffer win) buf))
  155. (select-window win))
  156. (one-window
  157. (goto-char (window-start win))
  158. (pop-to-buffer buffer)
  159. (setq win (selected-window))
  160. (enlarge-window (- target-height (window-height win))))
  161. (t
  162. (switch-to-buffer buf)))
  163. (if (and (not max-height)
  164. (> target-height (window-height (selected-window))))
  165. (progn (goto-char (window-start win))
  166. (enlarge-window (- target-height (window-height win)))))
  167. (goto-char (point-min))
  168. win)))
  169. ;; Avoid error in Emacs versions before 18.37.
  170. (defun one-window-p (&optional nomini)
  171. (eq (selected-window)
  172. (if (and nomini (zerop (minibuffer-depth)))
  173. (next-window) (next-window (next-window)))))