idle.el 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355
  1. ;;; idle.el --- Schedule parsing tasks in idle time
  2. ;; Copyright (C) 2003-2006, 2008-2017 Free Software Foundation, Inc.
  3. ;; Author: Eric M. Ludlam <zappo@gnu.org>
  4. ;; Keywords: syntax
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;
  18. ;; Originally, `semantic-auto-parse-mode' handled refreshing the
  19. ;; tags in a buffer in idle time. Other activities can be scheduled
  20. ;; in idle time, all of which require up-to-date tag tables.
  21. ;; Having a specialized idle time scheduler that first refreshes
  22. ;; the tags buffer, and then enables other idle time tasks reduces
  23. ;; the amount of work needed. Any specialized idle tasks need not
  24. ;; ask for a fresh tags list.
  25. ;;
  26. ;; NOTE ON SEMANTIC_ANALYZE
  27. ;;
  28. ;; Some of the idle modes use the semantic analyzer. The analyzer
  29. ;; automatically caches the created context, so it is shared amongst
  30. ;; all idle modes that will need it.
  31. (require 'semantic)
  32. (require 'semantic/ctxt)
  33. (require 'semantic/format)
  34. (require 'semantic/tag)
  35. (require 'timer)
  36. ;;(require 'working)
  37. ;; For the semantic-find-tags-by-name macro.
  38. (eval-when-compile (require 'semantic/find))
  39. (defvar eldoc-last-message)
  40. (declare-function eldoc-message "eldoc")
  41. (declare-function semantic-analyze-interesting-tag "semantic/analyze")
  42. (declare-function semantic-analyze-unsplit-name "semantic/analyze/fcn")
  43. (declare-function semantic-complete-analyze-inline-idle "semantic/complete")
  44. (declare-function semanticdb-deep-find-tags-by-name "semantic/db-find")
  45. (declare-function semanticdb-save-all-db-idle "semantic/db")
  46. (declare-function semanticdb-typecache-refresh-for-buffer "semantic/db-typecache")
  47. (declare-function semantic-decorate-flush-pending-decorations
  48. "semantic/decorate/mode")
  49. (declare-function pulse-momentary-highlight-region "pulse")
  50. (declare-function pulse-momentary-highlight-overlay "pulse")
  51. (declare-function semantic-symref-hits-in-region "semantic/symref/filter")
  52. ;;; Code:
  53. ;;; TIMER RELATED FUNCTIONS
  54. ;;
  55. (defvar semantic-idle-scheduler-timer nil
  56. "Timer used to schedule tasks in idle time.")
  57. (defvar semantic-idle-scheduler-work-timer nil
  58. "Timer used to schedule tasks in idle time that may take a while.")
  59. (defcustom semantic-idle-scheduler-verbose-flag nil
  60. "Non-nil means that the idle scheduler should provide debug messages.
  61. Use this setting to debug idle activities."
  62. :group 'semantic
  63. :type 'boolean)
  64. (defcustom semantic-idle-scheduler-idle-time 1
  65. "Time in seconds of idle before scheduling events.
  66. This time should be short enough to ensure that idle-scheduler will be
  67. run as soon as Emacs is idle."
  68. :group 'semantic
  69. :type 'number
  70. :set (lambda (sym val)
  71. (set-default sym val)
  72. (when (timerp semantic-idle-scheduler-timer)
  73. (cancel-timer semantic-idle-scheduler-timer)
  74. (setq semantic-idle-scheduler-timer nil)
  75. (semantic-idle-scheduler-setup-timers))))
  76. (defcustom semantic-idle-scheduler-work-idle-time 60
  77. "Time in seconds of idle before scheduling big work.
  78. This time should be long enough that once any big work is started, it is
  79. unlikely the user would be ready to type again right away."
  80. :group 'semantic
  81. :type 'number
  82. :set (lambda (sym val)
  83. (set-default sym val)
  84. (when (timerp semantic-idle-scheduler-timer)
  85. (cancel-timer semantic-idle-scheduler-timer)
  86. (setq semantic-idle-scheduler-timer nil)
  87. (semantic-idle-scheduler-setup-timers))))
  88. (defun semantic-idle-scheduler-setup-timers ()
  89. "Lazy initialization of the auto parse idle timer."
  90. ;; REFRESH THIS FUNCTION for XEMACS FOIBLES
  91. (or (timerp semantic-idle-scheduler-timer)
  92. (setq semantic-idle-scheduler-timer
  93. (run-with-idle-timer
  94. semantic-idle-scheduler-idle-time t
  95. #'semantic-idle-scheduler-function)))
  96. (or (timerp semantic-idle-scheduler-work-timer)
  97. (setq semantic-idle-scheduler-work-timer
  98. (run-with-idle-timer
  99. semantic-idle-scheduler-work-idle-time t
  100. #'semantic-idle-scheduler-work-function)))
  101. )
  102. (defun semantic-idle-scheduler-kill-timer ()
  103. "Kill the auto parse idle timer."
  104. (if (timerp semantic-idle-scheduler-timer)
  105. (cancel-timer semantic-idle-scheduler-timer))
  106. (setq semantic-idle-scheduler-timer nil))
  107. ;;; MINOR MODE
  108. ;;
  109. ;; The minor mode portion of this code just sets up the minor mode
  110. ;; which does the initial scheduling of the idle timers.
  111. ;;
  112. (defcustom semantic-idle-scheduler-mode-hook nil
  113. "Hook run at the end of the function `semantic-idle-scheduler-mode'."
  114. :group 'semantic
  115. :type 'hook)
  116. (defvar semantic-idle-scheduler-mode nil
  117. "Non-nil if idle-scheduler minor mode is enabled.
  118. Use the command `semantic-idle-scheduler-mode' to change this variable.")
  119. (make-variable-buffer-local 'semantic-idle-scheduler-mode)
  120. (defcustom semantic-idle-scheduler-max-buffer-size 0
  121. "Maximum size in bytes of buffers where idle-scheduler is enabled.
  122. If this value is less than or equal to 0, idle-scheduler is enabled in
  123. all buffers regardless of their size."
  124. :group 'semantic
  125. :type 'number)
  126. (defsubst semantic-idle-scheduler-enabled-p ()
  127. "Return non-nil if idle-scheduler is enabled for this buffer.
  128. idle-scheduler is disabled when debugging or if the buffer size
  129. exceeds the `semantic-idle-scheduler-max-buffer-size' threshold."
  130. (let* ((remote-file? (when (stringp buffer-file-name) (file-remote-p buffer-file-name))))
  131. (and semantic-idle-scheduler-mode
  132. (not (and (boundp 'semantic-debug-enabled)
  133. semantic-debug-enabled))
  134. (not semantic-lex-debug)
  135. ;; local file should exist on disk
  136. ;; remote file should have active connection
  137. (or (and (null remote-file?) (stringp buffer-file-name)
  138. (file-exists-p buffer-file-name))
  139. (and remote-file? (file-remote-p buffer-file-name nil t)))
  140. (or (<= semantic-idle-scheduler-max-buffer-size 0)
  141. (< (buffer-size) semantic-idle-scheduler-max-buffer-size)))))
  142. ;;;###autoload
  143. (define-minor-mode semantic-idle-scheduler-mode
  144. "Minor mode to auto parse buffer following a change.
  145. When this mode is off, a buffer is only rescanned for tokens when
  146. some command requests the list of available tokens. When idle-scheduler
  147. is enabled, Emacs periodically checks to see if the buffer is out of
  148. date, and reparses while the user is idle (not typing.)
  149. With prefix argument ARG, turn on if positive, otherwise off. The
  150. minor mode can be turned on only if semantic feature is available and
  151. the current buffer was set up for parsing. Return non-nil if the
  152. minor mode is enabled."
  153. nil nil nil
  154. (if semantic-idle-scheduler-mode
  155. (if (not (and (featurep 'semantic) (semantic-active-p)))
  156. (progn
  157. ;; Disable minor mode if semantic stuff not available
  158. (setq semantic-idle-scheduler-mode nil)
  159. (error "Buffer %s was not set up idle time scheduling"
  160. (buffer-name)))
  161. (semantic-idle-scheduler-setup-timers))))
  162. (semantic-add-minor-mode 'semantic-idle-scheduler-mode
  163. "ARP")
  164. ;;; SERVICES services
  165. ;;
  166. ;; These are services for managing idle services.
  167. ;;
  168. (defvar semantic-idle-scheduler-queue nil
  169. "List of functions to execute during idle time.
  170. These functions will be called in the current buffer after that
  171. buffer has had its tags made up to date. These functions
  172. will not be called if there are errors parsing the
  173. current buffer.")
  174. (defun semantic-idle-scheduler-add (function)
  175. "Schedule FUNCTION to occur during idle time."
  176. (add-to-list 'semantic-idle-scheduler-queue function))
  177. (defun semantic-idle-scheduler-remove (function)
  178. "Unschedule FUNCTION to occur during idle time."
  179. (setq semantic-idle-scheduler-queue
  180. (delete function semantic-idle-scheduler-queue)))
  181. ;;; IDLE Function
  182. ;;
  183. (defun semantic-idle-core-handler ()
  184. "Core idle function that handles reparsing.
  185. And also manages services that depend on tag values."
  186. (when semantic-idle-scheduler-verbose-flag
  187. (message "IDLE: Core handler..."))
  188. ;; FIXME: Use `while-no-input'?
  189. (semantic-exit-on-input 'idle-timer
  190. (let* ((inhibit-quit nil)
  191. (buffers (delq (current-buffer)
  192. (delq nil
  193. (mapcar #'(lambda (b)
  194. (and (buffer-file-name b)
  195. b))
  196. (buffer-list)))))
  197. safe ;; This safe is not used, but could be.
  198. others
  199. mode)
  200. (when (semantic-idle-scheduler-enabled-p)
  201. (save-excursion
  202. ;; First, reparse the current buffer.
  203. (setq mode major-mode
  204. safe (semantic-safe "Idle Parse Error: %S"
  205. ;(error "Goofy error 1")
  206. (semantic-idle-scheduler-refresh-tags)
  207. )
  208. )
  209. ;; Now loop over other buffers with same major mode, trying to
  210. ;; update them as well. Stop on keypress.
  211. (dolist (b buffers)
  212. (semantic-throw-on-input 'parsing-mode-buffers)
  213. (with-current-buffer b
  214. (if (eq major-mode mode)
  215. (and (semantic-idle-scheduler-enabled-p)
  216. (semantic-safe "Idle Parse Error: %S"
  217. ;(error "Goofy error")
  218. (semantic-idle-scheduler-refresh-tags)))
  219. (push (current-buffer) others))))
  220. (setq buffers others))
  221. ;; If re-parse of current buffer completed, evaluate all other
  222. ;; services. Stop on keypress.
  223. ;; NOTE ON COMMENTED SAFE HERE
  224. ;; We used to not execute the services if the buffer was
  225. ;; unparsable. We now assume that they are lexically
  226. ;; safe to do, because we have marked the buffer unparsable
  227. ;; if there was a problem.
  228. ;;(when safe
  229. (dolist (service semantic-idle-scheduler-queue)
  230. (save-excursion
  231. (semantic-throw-on-input 'idle-queue)
  232. (when semantic-idle-scheduler-verbose-flag
  233. (message "IDLE: execute service %s..." service))
  234. (semantic-safe (format "Idle Service Error %s: %%S" service)
  235. (funcall service))
  236. (when semantic-idle-scheduler-verbose-flag
  237. (message "IDLE: execute service %s...done" service))
  238. )))
  239. ;;)
  240. ;; Finally loop over remaining buffers, trying to update them as
  241. ;; well. Stop on keypress.
  242. (save-excursion
  243. (dolist (b buffers)
  244. (semantic-throw-on-input 'parsing-other-buffers)
  245. (with-current-buffer b
  246. (and (semantic-idle-scheduler-enabled-p)
  247. (semantic-idle-scheduler-refresh-tags)))))
  248. ))
  249. (when semantic-idle-scheduler-verbose-flag
  250. (message "IDLE: Core handler...done")))
  251. (defun semantic-debug-idle-function ()
  252. "Run the Semantic idle function with debugging turned on."
  253. (interactive)
  254. (let ((debug-on-error t))
  255. (semantic-idle-core-handler)
  256. ))
  257. (defun semantic-idle-scheduler-function ()
  258. "Function run when after `semantic-idle-scheduler-idle-time'.
  259. This function will reparse the current buffer, and if successful,
  260. call additional functions registered with the timer calls."
  261. (when (zerop (recursion-depth))
  262. (let ((debug-on-error nil))
  263. (save-match-data (semantic-idle-core-handler))
  264. )))
  265. ;;; WORK FUNCTION
  266. ;;
  267. ;; Unlike the shorter timer, the WORK timer will kick of tasks that
  268. ;; may take a long time to complete.
  269. (defcustom semantic-idle-work-parse-neighboring-files-flag nil
  270. "Non-nil means to parse files in the same dir as the current buffer.
  271. Disable to prevent lots of excessive parsing in idle time."
  272. :group 'semantic
  273. :type 'boolean)
  274. (defcustom semantic-idle-work-update-headers-flag nil
  275. "Non-nil means to parse through header files in idle time.
  276. Disable to prevent idle time parsing of many files. If completion
  277. is called that work will be done then instead."
  278. :group 'semantic
  279. :type 'boolean)
  280. (defun semantic-idle-work-for-one-buffer (buffer)
  281. "Do long-processing work for BUFFER.
  282. Uses `semantic-safe' and returns the output.
  283. Returns t if all processing succeeded."
  284. (with-current-buffer buffer
  285. (not (and
  286. ;; Just in case
  287. (semantic-safe "Idle Work Parse Error: %S"
  288. (semantic-idle-scheduler-refresh-tags)
  289. t)
  290. ;; Option to disable this work.
  291. semantic-idle-work-update-headers-flag
  292. ;; Force all our include files to get read in so we
  293. ;; are ready to provide good smart completion and idle
  294. ;; summary information
  295. (semantic-safe "Idle Work Including Error: %S"
  296. ;; Get the include related path.
  297. (when (and (featurep 'semantic/db) (semanticdb-minor-mode-p))
  298. (require 'semantic/db-find)
  299. (semanticdb-find-translate-path buffer nil)
  300. )
  301. t)
  302. ;; Pre-build the typecaches as needed.
  303. (semantic-safe "Idle Work Typecaching Error: %S"
  304. (when (featurep 'semantic/db-typecache)
  305. (semanticdb-typecache-refresh-for-buffer buffer))
  306. t)
  307. ))
  308. ))
  309. (defun semantic-idle-work-core-handler ()
  310. "Core handler for idle work processing of long running tasks.
  311. Visits Semantic controlled buffers, and makes sure all needed
  312. include files have been parsed, and that the typecache is up to date.
  313. Uses `semantic-idle-work-for-on-buffer' to do the work."
  314. (let ((errbuf nil)
  315. (interrupted
  316. (semantic-exit-on-input 'idle-work-timer
  317. (let* ((inhibit-quit nil)
  318. (cb (current-buffer))
  319. (buffers (delq (current-buffer)
  320. (delq nil
  321. (mapcar #'(lambda (b)
  322. (and (buffer-file-name b)
  323. b))
  324. (buffer-list)))))
  325. safe errbuf)
  326. ;; First, handle long tasks in the current buffer.
  327. (when (semantic-idle-scheduler-enabled-p)
  328. (save-excursion
  329. (setq safe (semantic-idle-work-for-one-buffer (current-buffer))
  330. )))
  331. (when (not safe) (push (current-buffer) errbuf))
  332. ;; Now loop over other buffers with same major mode, trying to
  333. ;; update them as well. Stop on keypress.
  334. (dolist (b buffers)
  335. (semantic-throw-on-input 'parsing-mode-buffers)
  336. (with-current-buffer b
  337. (when (semantic-idle-scheduler-enabled-p)
  338. (and (semantic-idle-scheduler-enabled-p)
  339. (unless (semantic-idle-work-for-one-buffer (current-buffer))
  340. (push (current-buffer) errbuf)))
  341. ))
  342. )
  343. (when (and (featurep 'semantic/db) (semanticdb-minor-mode-p))
  344. ;; Save everything.
  345. (semanticdb-save-all-db-idle)
  346. ;; Parse up files near our active buffer
  347. (when semantic-idle-work-parse-neighboring-files-flag
  348. (semantic-safe "Idle Work Parse Neighboring Files: %S"
  349. (set-buffer cb)
  350. (semantic-idle-scheduler-work-parse-neighboring-files))
  351. t)
  352. ;; Save everything... again
  353. (semanticdb-save-all-db-idle)
  354. )
  355. ;; Done w/ processing
  356. nil))))
  357. ;; Done
  358. (if interrupted
  359. "Interrupted"
  360. (cond ((not errbuf)
  361. "done")
  362. ((not (cdr errbuf))
  363. (format "done with 1 error in %s" (car errbuf)))
  364. (t
  365. (format "done with errors in %d buffers."
  366. (length errbuf)))))))
  367. (defun semantic-debug-idle-work-function ()
  368. "Run the Semantic idle work function with debugging turned on."
  369. (interactive)
  370. (let ((debug-on-error t))
  371. (semantic-idle-work-core-handler)
  372. ))
  373. (defun semantic-idle-scheduler-work-function ()
  374. "Function run when after `semantic-idle-scheduler-work-idle-time'.
  375. This routine handles difficult tasks that require a lot of parsing, such as
  376. parsing all the header files used by our active sources, or building up complex
  377. datasets."
  378. (when semantic-idle-scheduler-verbose-flag
  379. (message "Long Work Idle Timer..."))
  380. (let ((exit-type (save-match-data
  381. (semantic-idle-work-core-handler))))
  382. (when semantic-idle-scheduler-verbose-flag
  383. (message "Long Work Idle Timer...%s" exit-type)))
  384. )
  385. (defun semantic-idle-scheduler-work-parse-neighboring-files ()
  386. "Parse all the files in similar directories to buffers being edited."
  387. ;; Let's tell EDE to ignore all the files we're about to load
  388. (let ((ede-auto-add-method 'never)
  389. (matching-auto-mode-patterns nil))
  390. ;; Collect all patterns matching files of the same mode we edit.
  391. (mapc (lambda (pat) (and (eq (cdr pat) major-mode)
  392. (push (car pat) matching-auto-mode-patterns)))
  393. auto-mode-alist)
  394. ;; Loop over all files, and if one matches our mode, we force its
  395. ;; table to load.
  396. (dolist (file (directory-files default-directory t ".*" t))
  397. (catch 'found
  398. (mapc (lambda (pat)
  399. (semantic-throw-on-input 'parsing-mode-buffers)
  400. ;; We use string-match instead of passing the pattern
  401. ;; into directory files, because some patterns don't
  402. ;; work with directory files.
  403. (and (string-match pat file)
  404. (save-excursion
  405. (semanticdb-file-table-object file))
  406. (throw 'found t)))
  407. matching-auto-mode-patterns)))))
  408. ;;; REPARSING
  409. ;;
  410. ;; Reparsing is installed as semantic idle service.
  411. ;; This part ALWAYS happens, and other services occur
  412. ;; afterwards.
  413. (defvar semantic-before-idle-scheduler-reparse-hook nil
  414. "Hook run before option `semantic-idle-scheduler' begins parsing.
  415. If any hook function throws an error, this variable is reset to nil.
  416. This hook is not protected from lexical errors.")
  417. (defvar semantic-after-idle-scheduler-reparse-hook nil
  418. "Hook run after option `semantic-idle-scheduler' has parsed.
  419. If any hook function throws an error, this variable is reset to nil.
  420. This hook is not protected from lexical errors.")
  421. (semantic-varalias-obsolete 'semantic-before-idle-scheduler-reparse-hooks
  422. 'semantic-before-idle-scheduler-reparse-hook "23.2")
  423. (semantic-varalias-obsolete 'semantic-after-idle-scheduler-reparse-hooks
  424. 'semantic-after-idle-scheduler-reparse-hook "23.2")
  425. (defun semantic-idle-scheduler-refresh-tags ()
  426. "Refreshes the current buffer's tags.
  427. This is called by `semantic-idle-scheduler-function' to update the
  428. tags in the current buffer.
  429. Return non-nil if the refresh was successful.
  430. Return nil if there is some sort of syntax error preventing a full
  431. reparse.
  432. Does nothing if the current buffer doesn't need reparsing."
  433. (prog1
  434. ;; These checks actually occur in `semantic-fetch-tags', but if we
  435. ;; do them here, then all the bovination hooks are not run, and
  436. ;; we save lots of time.
  437. (cond
  438. ;; If the buffer was previously marked unparsable,
  439. ;; then don't waste our time.
  440. ((semantic-parse-tree-unparseable-p)
  441. nil)
  442. ;; The parse tree is already ok.
  443. ((semantic-parse-tree-up-to-date-p)
  444. t)
  445. (t
  446. ;; If the buffer might need a reparse and it is safe to do so,
  447. ;; give it a try.
  448. (let* (;(semantic-working-type nil)
  449. (inhibit-quit nil)
  450. ;; (working-use-echo-area-p
  451. ;; (not semantic-idle-scheduler-working-in-modeline-flag))
  452. ;; (working-status-dynamic-type
  453. ;; (if semantic-idle-scheduler-no-working-message
  454. ;; nil
  455. ;; working-status-dynamic-type))
  456. ;; (working-status-percentage-type
  457. ;; (if semantic-idle-scheduler-no-working-message
  458. ;; nil
  459. ;; working-status-percentage-type))
  460. (lexically-safe t)
  461. )
  462. ;; Let people hook into this, but don't let them hose
  463. ;; us over!
  464. (condition-case nil
  465. (run-hooks 'semantic-before-idle-scheduler-reparse-hook)
  466. (error (setq semantic-before-idle-scheduler-reparse-hook nil)))
  467. (unwind-protect
  468. ;; Perform the parsing.
  469. (progn
  470. (when semantic-idle-scheduler-verbose-flag
  471. (message "IDLE: reparse %s..." (buffer-name)))
  472. (when (semantic-lex-catch-errors idle-scheduler
  473. (save-excursion (semantic-fetch-tags))
  474. nil)
  475. ;; If we are here, it is because the lexical step failed,
  476. ;; probably due to unterminated lists or something like that.
  477. ;; We do nothing, and just wait for the next idle timer
  478. ;; to go off. In the meantime, remember this, and make sure
  479. ;; no other idle services can get executed.
  480. (setq lexically-safe nil))
  481. (when semantic-idle-scheduler-verbose-flag
  482. (message "IDLE: reparse %s...done" (buffer-name))))
  483. ;; Let people hook into this, but don't let them hose
  484. ;; us over!
  485. (condition-case nil
  486. (run-hooks 'semantic-after-idle-scheduler-reparse-hook)
  487. (error (setq semantic-after-idle-scheduler-reparse-hook nil))))
  488. ;; Return if we are lexically safe (from prog1)
  489. lexically-safe)))
  490. ;; After updating the tags, handle any pending decorations for this
  491. ;; buffer.
  492. (require 'semantic/decorate/mode)
  493. (semantic-decorate-flush-pending-decorations (current-buffer))
  494. ))
  495. ;;; IDLE SERVICES
  496. ;;
  497. ;; Idle Services are minor modes which enable or disable a services in
  498. ;; the idle scheduler. Creating a new services only requires calling
  499. ;; `semantic-create-idle-services' which does all the setup
  500. ;; needed to create the minor mode that will enable or disable
  501. ;; a services. The services must provide a single function.
  502. ;; FIXME doc is incomplete.
  503. (defmacro define-semantic-idle-service (name doc &rest forms)
  504. "Create a new idle services with NAME.
  505. DOC will be a documentation string describing FORMS.
  506. FORMS will be called during idle time after the current buffer's
  507. semantic tag information has been updated.
  508. This routine creates the following functions and variables:"
  509. (let ((global (intern (concat "global-" (symbol-name name) "-mode")))
  510. (mode (intern (concat (symbol-name name) "-mode")))
  511. (hook (intern (concat (symbol-name name) "-mode-hook")))
  512. (map (intern (concat (symbol-name name) "-mode-map")))
  513. (setup (intern (concat (symbol-name name) "-mode-setup")))
  514. (func (intern (concat (symbol-name name) "-idle-function"))))
  515. `(progn
  516. (define-minor-mode ,global
  517. ,(concat "Toggle " (symbol-name global) ".
  518. With ARG, turn the minor mode on if ARG is positive, off otherwise.
  519. When this minor mode is enabled, `" (symbol-name mode) "' is
  520. turned on in every Semantic-supported buffer.")
  521. :global t
  522. :group 'semantic
  523. :group 'semantic-modes
  524. :require 'semantic/idle
  525. (semantic-toggle-minor-mode-globally
  526. ',mode (if ,global 1 -1)))
  527. ;; FIXME: Get rid of this when define-minor-mode does it for us.
  528. (defcustom ,hook nil
  529. ,(concat "Hook run at the end of function `" (symbol-name mode) "'.")
  530. :group 'semantic
  531. :type 'hook)
  532. (defvar ,map
  533. (let ((km (make-sparse-keymap)))
  534. km)
  535. ,(concat "Keymap for `" (symbol-name mode) "'."))
  536. (define-minor-mode ,mode
  537. ,doc
  538. :keymap ,map
  539. (if ,mode
  540. (if (not (and (featurep 'semantic) (semantic-active-p)))
  541. (progn
  542. ;; Disable minor mode if semantic stuff not available
  543. (setq ,mode nil)
  544. (error "Buffer %s was not set up for parsing"
  545. (buffer-name)))
  546. ;; Enable the mode mode
  547. (semantic-idle-scheduler-add #',func))
  548. ;; Disable the mode mode
  549. (semantic-idle-scheduler-remove #',func)))
  550. (semantic-add-minor-mode ',mode
  551. "") ; idle schedulers are quiet?
  552. (defun ,func ()
  553. ,(concat "Perform idle activity for the minor mode `"
  554. (symbol-name mode) "'.")
  555. ,@forms))))
  556. (put 'define-semantic-idle-service 'lisp-indent-function 1)
  557. (add-hook 'edebug-setup-hook
  558. (lambda ()
  559. (def-edebug-spec define-semantic-idle-service
  560. (&define name stringp def-body))))
  561. ;;; SUMMARY MODE
  562. ;;
  563. ;; A mode similar to eldoc using semantic
  564. (defcustom semantic-idle-truncate-long-summaries t
  565. "Truncate summaries that are too long to fit in the minibuffer.
  566. This can prevent minibuffer resizing in idle time."
  567. :group 'semantic
  568. :type 'boolean)
  569. (defcustom semantic-idle-summary-function
  570. 'semantic-format-tag-summarize-with-file
  571. "Function to call when displaying tag information during idle time.
  572. This function should take a single argument, a Semantic tag, and
  573. return a string to display.
  574. Some useful functions are found in `semantic-format-tag-functions'."
  575. :group 'semantic
  576. :type semantic-format-tag-custom-list)
  577. (defsubst semantic-idle-summary-find-current-symbol-tag (sym)
  578. "Search for a semantic tag with name SYM in database tables.
  579. Return the tag found or nil if not found.
  580. If semanticdb is not in use, use the current buffer only."
  581. (car (if (and (featurep 'semantic/db)
  582. semanticdb-current-database
  583. (require 'semantic/db-find))
  584. (cdar (semanticdb-deep-find-tags-by-name sym))
  585. (semantic-deep-find-tags-by-name sym (current-buffer)))))
  586. (defun semantic-idle-summary-current-symbol-info-brutish ()
  587. "Return a string message describing the current context.
  588. Gets a symbol with `semantic-ctxt-current-thing' and then
  589. tries to find it with a deep targeted search."
  590. ;; Try the current "thing".
  591. (let ((sym (car (semantic-ctxt-current-thing))))
  592. (when sym
  593. (semantic-idle-summary-find-current-symbol-tag sym))))
  594. (defun semantic-idle-summary-current-symbol-keyword ()
  595. "Return a string message describing the current symbol.
  596. Returns a value only if it is a keyword."
  597. ;; Try the current "thing".
  598. (let ((sym (car (semantic-ctxt-current-thing))))
  599. (if (and sym (semantic-lex-keyword-p sym))
  600. (semantic-lex-keyword-get sym 'summary))))
  601. (defun semantic-idle-summary-current-symbol-info-context ()
  602. "Return a string message describing the current context.
  603. Use the semantic analyzer to find the symbol information."
  604. (let ((analysis (condition-case nil
  605. (semantic-analyze-current-context (point))
  606. (error nil))))
  607. (when analysis
  608. (require 'semantic/analyze)
  609. (semantic-analyze-interesting-tag analysis))))
  610. (defun semantic-idle-summary-current-symbol-info-default ()
  611. "Return a string message describing the current context.
  612. This function will disable loading of previously unloaded files
  613. by semanticdb as a time-saving measure."
  614. (semanticdb-without-unloaded-file-searches
  615. (save-excursion
  616. ;; use whichever has success first.
  617. (or
  618. (semantic-idle-summary-current-symbol-keyword)
  619. (semantic-idle-summary-current-symbol-info-context)
  620. (semantic-idle-summary-current-symbol-info-brutish)
  621. ))))
  622. (defvar semantic-idle-summary-out-of-context-faces
  623. '(
  624. font-lock-comment-face
  625. font-lock-string-face
  626. font-lock-doc-string-face ; XEmacs.
  627. font-lock-doc-face ; Emacs 21 and later.
  628. )
  629. "List of font-lock faces that indicate a useless summary context.
  630. Those are generally faces used to highlight comments.
  631. It might be useful to override this variable to add comment faces
  632. specific to a major mode. For example, in jde mode:
  633. \(defvar-mode-local jde-mode semantic-idle-summary-out-of-context-faces
  634. (append (default-value \\='semantic-idle-summary-out-of-context-faces)
  635. \\='(jde-java-font-lock-doc-tag-face
  636. jde-java-font-lock-link-face
  637. jde-java-font-lock-bold-face
  638. jde-java-font-lock-underline-face
  639. jde-java-font-lock-pre-face
  640. jde-java-font-lock-code-face)))")
  641. (defun semantic-idle-summary-useful-context-p ()
  642. "Non-nil if we should show a summary based on context."
  643. (if (and (boundp 'font-lock-mode)
  644. font-lock-mode
  645. (memq (get-text-property (point) 'face)
  646. semantic-idle-summary-out-of-context-faces))
  647. ;; The best I can think of at the moment is to disable
  648. ;; in comments by detecting with font-lock.
  649. nil
  650. t))
  651. (define-overloadable-function semantic-idle-summary-current-symbol-info ()
  652. "Return a string message describing the current context.")
  653. (make-obsolete-overload 'semantic-eldoc-current-symbol-info
  654. 'semantic-idle-summary-current-symbol-info
  655. "23.2")
  656. (defcustom semantic-idle-summary-mode-hook nil
  657. "Hook run at the end of `semantic-idle-summary'."
  658. :group 'semantic
  659. :type 'hook)
  660. (defun semantic-idle-summary-idle-function ()
  661. "Display a tag summary of the lexical token under the cursor.
  662. Call `semantic-idle-summary-current-symbol-info' for getting the
  663. current tag to display information."
  664. (or (eq major-mode 'emacs-lisp-mode)
  665. (not (semantic-idle-summary-useful-context-p))
  666. (let* ((found (semantic-idle-summary-current-symbol-info))
  667. (str (cond ((stringp found) found)
  668. ((semantic-tag-p found)
  669. (funcall semantic-idle-summary-function
  670. found nil t)))))
  671. ;; Show the message with eldoc functions
  672. (unless (and str (boundp 'eldoc-echo-area-use-multiline-p)
  673. eldoc-echo-area-use-multiline-p)
  674. (let ((w (1- (window-width (minibuffer-window)))))
  675. (if (> (length str) w)
  676. (setq str (substring str 0 w)))))
  677. ;; I borrowed some bits from eldoc to shorten the
  678. ;; message.
  679. (when semantic-idle-truncate-long-summaries
  680. (let ((ea-width (1- (window-width (minibuffer-window))))
  681. (strlen (length str)))
  682. (when (> strlen ea-width)
  683. (setq str (substring str 0 ea-width)))))
  684. ;; Display it
  685. (eldoc-message str))))
  686. (define-minor-mode semantic-idle-summary-mode
  687. "Toggle Semantic Idle Summary mode.
  688. With ARG, turn Semantic Idle Summary mode on if ARG is positive,
  689. off otherwise.
  690. When this minor mode is enabled, the echo area displays a summary
  691. of the lexical token at point whenever Emacs is idle."
  692. :group 'semantic
  693. :group 'semantic-modes
  694. (if semantic-idle-summary-mode
  695. ;; Enable the mode
  696. (progn
  697. (unless (and (featurep 'semantic) (semantic-active-p))
  698. ;; Disable minor mode if semantic stuff not available
  699. (setq semantic-idle-summary-mode nil)
  700. (error "Buffer %s was not set up for parsing"
  701. (buffer-name)))
  702. (require 'eldoc)
  703. (semantic-idle-scheduler-add 'semantic-idle-summary-idle-function)
  704. (add-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area t))
  705. ;; Disable the mode
  706. (semantic-idle-scheduler-remove 'semantic-idle-summary-idle-function)
  707. (remove-hook 'pre-command-hook 'semantic-idle-summary-refresh-echo-area t)))
  708. (defun semantic-idle-summary-refresh-echo-area ()
  709. (and semantic-idle-summary-mode
  710. eldoc-last-message
  711. (if (and (not executing-kbd-macro)
  712. (not (and (boundp 'edebug-active) edebug-active))
  713. (not cursor-in-echo-area)
  714. (not (eq (selected-window) (minibuffer-window))))
  715. (eldoc-message eldoc-last-message)
  716. (setq eldoc-last-message nil))))
  717. (semantic-add-minor-mode 'semantic-idle-summary-mode "")
  718. (define-minor-mode global-semantic-idle-summary-mode
  719. "Toggle Global Semantic Idle Summary mode.
  720. With ARG, turn Global Semantic Idle Summary mode on if ARG is
  721. positive, off otherwise.
  722. When this minor mode is enabled, `semantic-idle-summary-mode' is
  723. turned on in every Semantic-supported buffer."
  724. :global t
  725. :group 'semantic
  726. :group 'semantic-modes
  727. (semantic-toggle-minor-mode-globally
  728. 'semantic-idle-summary-mode
  729. (if global-semantic-idle-summary-mode 1 -1)))
  730. ;;; Current symbol highlight
  731. ;;
  732. ;; This mode will use context analysis to perform highlighting
  733. ;; of all uses of the symbol that is under the cursor.
  734. ;;
  735. ;; This is to mimic the Eclipse tool of a similar nature.
  736. (defface semantic-idle-symbol-highlight
  737. '((t :inherit region))
  738. "Face used for highlighting local symbols."
  739. :group 'semantic-faces)
  740. (defvar semantic-idle-symbol-highlight-face 'semantic-idle-symbol-highlight
  741. "Face used for highlighting local symbols.")
  742. (make-obsolete-variable 'semantic-idle-symbol-highlight-face
  743. "customize the face `semantic-idle-symbol-highlight' instead" "24.4" 'set)
  744. (defun semantic-idle-symbol-maybe-highlight (tag)
  745. "Perhaps add highlighting to the symbol represented by TAG.
  746. TAG was found as the symbol under point. If it happens to be
  747. visible, then highlight it."
  748. (require 'pulse)
  749. (let* ((region (when (and (semantic-tag-p tag)
  750. (semantic-tag-with-position-p tag))
  751. (semantic-tag-overlay tag)))
  752. (file (when (and (semantic-tag-p tag)
  753. (semantic-tag-with-position-p tag))
  754. (semantic-tag-file-name tag)))
  755. (buffer (when file (get-file-buffer file)))
  756. ;; We use pulse, but we don't want the flashy version,
  757. ;; just the stable version.
  758. (pulse-flag nil)
  759. )
  760. (cond ((semantic-overlay-p region)
  761. (with-current-buffer (semantic-overlay-buffer region)
  762. (save-excursion
  763. (goto-char (semantic-overlay-start region))
  764. (when (pos-visible-in-window-p
  765. (point) (get-buffer-window (current-buffer) 'visible))
  766. (if (< (semantic-overlay-end region) (point-at-eol))
  767. (pulse-momentary-highlight-overlay
  768. region semantic-idle-symbol-highlight-face)
  769. ;; Not the same
  770. (pulse-momentary-highlight-region
  771. (semantic-overlay-start region)
  772. (point-at-eol)
  773. semantic-idle-symbol-highlight-face))))
  774. ))
  775. ((vectorp region)
  776. (let ((start (aref region 0))
  777. (end (aref region 1)))
  778. (save-excursion
  779. (when buffer (set-buffer buffer))
  780. ;; As a vector, we have no filename. Perhaps it is a
  781. ;; local variable?
  782. (when (and (<= end (point-max))
  783. (pos-visible-in-window-p
  784. start (get-buffer-window (current-buffer) 'visible)))
  785. (goto-char start)
  786. (when (re-search-forward
  787. (regexp-quote (semantic-tag-name tag))
  788. end t)
  789. ;; This is likely it, give it a try.
  790. (pulse-momentary-highlight-region
  791. start (if (<= end (point-at-eol)) end
  792. (point-at-eol))
  793. semantic-idle-symbol-highlight-face)))
  794. ))))
  795. nil))
  796. (define-semantic-idle-service semantic-idle-local-symbol-highlight
  797. "Highlight the tag and symbol references of the symbol under point.
  798. Call `semantic-analyze-current-context' to find the reference tag.
  799. Call `semantic-symref-hits-in-region' to identify local references."
  800. (require 'pulse)
  801. (when (semantic-idle-summary-useful-context-p)
  802. (let* ((ctxt
  803. (semanticdb-without-unloaded-file-searches
  804. (semantic-analyze-current-context)))
  805. (Hbounds (when ctxt (oref ctxt bounds)))
  806. (target (when ctxt (car (reverse (oref ctxt prefix)))))
  807. (tag (semantic-current-tag))
  808. ;; We use pulse, but we don't want the flashy version,
  809. ;; just the stable version.
  810. (pulse-flag nil))
  811. (when (and ctxt tag)
  812. ;; Highlight the original tag? Protect against problems.
  813. (condition-case nil
  814. (semantic-idle-symbol-maybe-highlight target)
  815. (error nil))
  816. ;; Identify all hits in this current tag.
  817. (when (semantic-tag-p target)
  818. (require 'semantic/symref/filter)
  819. (semantic-symref-hits-in-region
  820. target (lambda (start end prefix)
  821. (when (/= start (car Hbounds))
  822. (pulse-momentary-highlight-region
  823. start end semantic-idle-symbol-highlight-face))
  824. (semantic-throw-on-input 'symref-highlight)
  825. )
  826. (semantic-tag-start tag)
  827. (semantic-tag-end tag)))
  828. ))))
  829. ;;;###autoload
  830. (define-minor-mode global-semantic-idle-scheduler-mode
  831. "Toggle global use of option `semantic-idle-scheduler-mode'.
  832. The idle scheduler will automatically reparse buffers in idle time,
  833. and then schedule other jobs setup with `semantic-idle-scheduler-add'.
  834. If ARG is positive or nil, enable, if it is negative, disable."
  835. :global t
  836. :group 'semantic
  837. :group 'semantic-modes
  838. ;; When turning off, disable other idle modes.
  839. (when (null global-semantic-idle-scheduler-mode)
  840. (global-semantic-idle-summary-mode -1)
  841. (global-semantic-idle-local-symbol-highlight-mode -1)
  842. (global-semantic-idle-completions-mode -1))
  843. (semantic-toggle-minor-mode-globally
  844. 'semantic-idle-scheduler-mode
  845. (if global-semantic-idle-scheduler-mode 1 -1)))
  846. ;;; Completion Popup Mode
  847. ;;
  848. ;; This mode uses tooltips to display a (hopefully) short list of possible
  849. ;; completions available for the text under point. It provides
  850. ;; NO provision for actually filling in the values from those completions.
  851. (defun semantic-idle-completions-end-of-symbol-p ()
  852. "Return non-nil if the cursor is at the END of a symbol.
  853. If the cursor is in the middle of a symbol, then we shouldn't be
  854. doing fancy completions."
  855. (not (looking-at "\\w\\|\\s_")))
  856. (defun semantic-idle-completion-list-default ()
  857. "Calculate and display a list of completions."
  858. (when (and (semantic-idle-summary-useful-context-p)
  859. (semantic-idle-completions-end-of-symbol-p))
  860. ;; This mode can be fragile, hence don't raise errors, and only
  861. ;; report problems if semantic-idle-scheduler-verbose-flag is
  862. ;; non-nil. If something doesn't do what you expect, run the
  863. ;; below command by hand instead.
  864. (condition-case err
  865. (semanticdb-without-unloaded-file-searches
  866. ;; Use idle version.
  867. (semantic-complete-analyze-inline-idle)
  868. )
  869. (error
  870. (when semantic-idle-scheduler-verbose-flag
  871. (message " %s" (error-message-string err)))))
  872. ))
  873. (define-semantic-idle-service semantic-idle-completions
  874. "Toggle Semantic Idle Completions mode.
  875. With ARG, turn Semantic Idle Completions mode on if ARG is
  876. positive, off otherwise.
  877. This minor mode only takes effect if Semantic is active and
  878. `semantic-idle-scheduler-mode' is enabled.
  879. When enabled, Emacs displays a list of possible completions at
  880. idle time. The method for displaying completions is given by
  881. `semantic-complete-inline-analyzer-idle-displayor-class'; the
  882. default is to show completions inline.
  883. While a completion is displayed, RET accepts the completion; M-n
  884. and M-p cycle through completion alternatives; TAB attempts to
  885. complete as far as possible, and cycles if no additional
  886. completion is possible; and any other command cancels the
  887. completion.
  888. \\{semantic-complete-inline-map}"
  889. ;; Add the ability to override sometime.
  890. (semantic-idle-completion-list-default))
  891. ;;; Breadcrumbs for tag under point
  892. ;;
  893. ;; Service that displays a breadcrumbs indication of the tag under
  894. ;; point and its parents in the header or mode line.
  895. ;;
  896. (defcustom semantic-idle-breadcrumbs-display-function
  897. #'semantic-idle-breadcrumbs--display-in-header-line
  898. "Function to display the tag under point in idle time.
  899. This function should take a list of Semantic tags as its only
  900. argument. The tags are sorted according to their nesting order,
  901. starting with the outermost tag. The function should call
  902. `semantic-idle-breadcrumbs-format-tag-list-function' to convert
  903. the tag list into a string."
  904. :group 'semantic
  905. :type '(choice
  906. (const :tag "Display in header line"
  907. semantic-idle-breadcrumbs--display-in-header-line)
  908. (const :tag "Display in mode line"
  909. semantic-idle-breadcrumbs--display-in-mode-line)
  910. (function :tag "Other function")))
  911. (defcustom semantic-idle-breadcrumbs-format-tag-list-function
  912. #'semantic-idle-breadcrumbs--format-linear
  913. "Function to format the list of tags containing point.
  914. This function should take a list of Semantic tags and an optional
  915. maximum length of the produced string as its arguments. The
  916. maximum length is a hint and can be ignored. When the maximum
  917. length is omitted, an unconstrained string should be
  918. produced. The tags are sorted according to their nesting order,
  919. starting with the outermost tag. Single tags should be formatted
  920. using `semantic-idle-breadcrumbs-format-tag-function' unless
  921. special formatting is required."
  922. :group 'semantic
  923. :type '(choice
  924. (const :tag "Format tags as list, innermost last"
  925. semantic-idle-breadcrumbs--format-linear)
  926. (const :tag "Innermost tag with details, followed by remaining tags"
  927. semantic-idle-breadcrumbs--format-innermost-first)
  928. (function :tag "Other function")))
  929. (defcustom semantic-idle-breadcrumbs-format-tag-function
  930. #'semantic-format-tag-abbreviate
  931. "Function to call to format information about tags.
  932. This function should take a single argument, a Semantic tag, and
  933. return a string to display.
  934. Some useful functions are found in `semantic-format-tag-functions'."
  935. :group 'semantic
  936. :type semantic-format-tag-custom-list)
  937. (defcustom semantic-idle-breadcrumbs-separator 'mode-specific
  938. "Specify how to separate tags in the breadcrumbs string.
  939. An arbitrary string or a mode-specific scope nesting
  940. string (like, for example, \"::\" in C++, or \".\" in Java) can
  941. be used."
  942. :group 'semantic
  943. :type '(choice
  944. (const :tag "Use mode specific separator"
  945. mode-specific)
  946. (string :tag "Specify separator string")))
  947. (defcustom semantic-idle-breadcrumbs-header-line-prefix
  948. semantic-stickyfunc-indent-string ;; TODO not optimal
  949. "String used to indent the breadcrumbs string.
  950. Customize this string to match the space used by scrollbars and
  951. fringe."
  952. :group 'semantic
  953. :type 'string)
  954. (defvar semantic-idle-breadcrumbs-popup-menu nil
  955. "Menu used when a tag displayed by `semantic-idle-breadcrumbs-mode' is clicked.")
  956. (defun semantic-idle-breadcrumbs--popup-menu (event)
  957. "Popup a menu that displays things to do to the clicked tag.
  958. Argument EVENT describes the event that caused this function to
  959. be called."
  960. (interactive "e")
  961. (let ((old-window (selected-window))
  962. (window (semantic-event-window event)))
  963. (select-window window t)
  964. (semantic-popup-menu semantic-idle-breadcrumbs-popup-menu)
  965. (select-window old-window)))
  966. (defmacro semantic-idle-breadcrumbs--tag-function (function)
  967. "Return lambda expression calling FUNCTION when called from a popup."
  968. `(lambda (event)
  969. (interactive "e")
  970. (let* ((old-window (selected-window))
  971. (window (semantic-event-window event))
  972. (column (car (nth 6 (nth 1 event)))) ;; TODO semantic-event-column?
  973. (tag (progn
  974. (select-window window t)
  975. (plist-get
  976. (text-properties-at column header-line-format)
  977. 'tag))))
  978. (,function tag)
  979. (select-window old-window)))
  980. )
  981. ;; TODO does this work for mode-line case?
  982. (defvar semantic-idle-breadcrumbs-popup-map
  983. (let ((map (make-sparse-keymap)))
  984. ;; mouse-1 goes to clicked tag
  985. (define-key map
  986. [ header-line mouse-1 ]
  987. (semantic-idle-breadcrumbs--tag-function
  988. semantic-go-to-tag))
  989. ;; mouse-3 pops up a context menu
  990. (define-key map
  991. [ header-line mouse-3 ]
  992. 'semantic-idle-breadcrumbs--popup-menu)
  993. map)
  994. "Keymap for semantic idle breadcrumbs minor mode.")
  995. (easy-menu-define
  996. semantic-idle-breadcrumbs-popup-menu
  997. semantic-idle-breadcrumbs-popup-map
  998. "Semantic Breadcrumbs Mode Menu"
  999. (list
  1000. "Breadcrumb Tag"
  1001. (semantic-menu-item
  1002. (vector
  1003. "Go to Tag"
  1004. (semantic-idle-breadcrumbs--tag-function
  1005. semantic-go-to-tag)
  1006. :active t
  1007. :help "Jump to this tag"))
  1008. ;; TODO these entries need minor changes (optional tag argument) in
  1009. ;; senator-copy-tag etc
  1010. ;; (semantic-menu-item
  1011. ;; (vector
  1012. ;; "Copy Tag"
  1013. ;; (semantic-idle-breadcrumbs--tag-function
  1014. ;; senator-copy-tag)
  1015. ;; :active t
  1016. ;; :help "Copy this tag"))
  1017. ;; (semantic-menu-item
  1018. ;; (vector
  1019. ;; "Kill Tag"
  1020. ;; (semantic-idle-breadcrumbs--tag-function
  1021. ;; senator-kill-tag)
  1022. ;; :active t
  1023. ;; :help "Kill tag text to the kill ring, and copy the tag to
  1024. ;; the tag ring"))
  1025. ;; (semantic-menu-item
  1026. ;; (vector
  1027. ;; "Copy Tag to Register"
  1028. ;; (semantic-idle-breadcrumbs--tag-function
  1029. ;; senator-copy-tag-to-register)
  1030. ;; :active t
  1031. ;; :help "Copy this tag"))
  1032. ;; (semantic-menu-item
  1033. ;; (vector
  1034. ;; "Narrow to Tag"
  1035. ;; (semantic-idle-breadcrumbs--tag-function
  1036. ;; senator-narrow-to-defun)
  1037. ;; :active t
  1038. ;; :help "Narrow to the bounds of the current tag"))
  1039. ;; (semantic-menu-item
  1040. ;; (vector
  1041. ;; "Fold Tag"
  1042. ;; (semantic-idle-breadcrumbs--tag-function
  1043. ;; senator-fold-tag-toggle)
  1044. ;; :active t
  1045. ;; :style 'toggle
  1046. ;; :selected '(let ((tag (semantic-current-tag)))
  1047. ;; (and tag (semantic-tag-folded-p tag)))
  1048. ;; :help "Fold the current tag to one line"))
  1049. "---"
  1050. (semantic-menu-item
  1051. (vector
  1052. "About this Header Line"
  1053. (lambda ()
  1054. (interactive)
  1055. (describe-function 'semantic-idle-breadcrumbs-mode))
  1056. :active t
  1057. :help "Display help about this header line."))
  1058. )
  1059. )
  1060. (define-semantic-idle-service semantic-idle-breadcrumbs
  1061. "Display breadcrumbs for the tag under point and its parents."
  1062. (let* ((scope (semantic-calculate-scope))
  1063. (tag-list (if scope
  1064. ;; If there is a scope, extract the tag and its
  1065. ;; parents.
  1066. (append (oref scope parents)
  1067. (when (oref scope tag)
  1068. (list (oref scope tag))))
  1069. ;; Fall back to tags by overlay
  1070. (semantic-find-tag-by-overlay))))
  1071. ;; Display the tags.
  1072. (funcall semantic-idle-breadcrumbs-display-function tag-list)))
  1073. (defun semantic-idle-breadcrumbs--display-in-header-line (tag-list)
  1074. "Display the tags in TAG-LIST in the header line of their buffer."
  1075. (let ((width (- (nth 2 (window-edges))
  1076. (nth 0 (window-edges)))))
  1077. ;; Format TAG-LIST and put the formatted string into the header
  1078. ;; line.
  1079. (setq header-line-format
  1080. (replace-regexp-in-string ;; Since % is interpreted in the
  1081. "\\(%\\)" "%\\1" ;; mode/header line format, we
  1082. (concat ;; have to escape all occurrences.
  1083. semantic-idle-breadcrumbs-header-line-prefix
  1084. (if tag-list
  1085. (semantic-idle-breadcrumbs--format-tag-list
  1086. tag-list
  1087. (- width
  1088. (length semantic-idle-breadcrumbs-header-line-prefix)))
  1089. (propertize
  1090. "<not on tags>"
  1091. 'face
  1092. 'font-lock-comment-face))))))
  1093. ;; Update the header line.
  1094. (force-mode-line-update))
  1095. (defun semantic-idle-breadcrumbs--display-in-mode-line (tag-list)
  1096. "Display the tags in TAG-LIST in the mode line of their buffer.
  1097. TODO THIS FUNCTION DOES NOT WORK YET."
  1098. (error "This function does not work yet")
  1099. (let ((width (- (nth 2 (window-edges))
  1100. (nth 0 (window-edges)))))
  1101. (setq mode-line-format
  1102. (replace-regexp-in-string ;; see comment in
  1103. "\\(%\\)" "%\\1" ;; `semantic-idle-breadcrumbs--display-in-header-line'
  1104. (semantic-idle-breadcrumbs--format-tag-list tag-list width))))
  1105. (force-mode-line-update))
  1106. (defun semantic-idle-breadcrumbs--format-tag-list (tag-list max-length)
  1107. "Format TAG-LIST using configured functions respecting MAX-LENGTH.
  1108. If the initial formatting result is longer than MAX-LENGTH, it is
  1109. shortened at the beginning."
  1110. ;; Format TAG-LIST using the configured formatting function.
  1111. (let* ((complete-format (funcall
  1112. semantic-idle-breadcrumbs-format-tag-list-function
  1113. tag-list max-length))
  1114. ;; Determine length of complete format.
  1115. (complete-length (length complete-format)))
  1116. ;; Shorten string if necessary.
  1117. (if (<= complete-length max-length)
  1118. complete-format
  1119. (concat "... "
  1120. (substring
  1121. complete-format
  1122. (- complete-length (- max-length 4))))))
  1123. )
  1124. (defun semantic-idle-breadcrumbs--format-linear
  1125. (tag-list &optional max-length)
  1126. "Format TAG-LIST as a linear list, starting with the outermost tag.
  1127. MAX-LENGTH is not used."
  1128. (require 'semantic/analyze/fcn)
  1129. (let* ((format-pieces (mapcar
  1130. #'semantic-idle-breadcrumbs--format-tag
  1131. tag-list))
  1132. ;; Format tag list, putting configured separators between the
  1133. ;; tags.
  1134. (complete-format (cond
  1135. ;; Mode specific separator.
  1136. ((eq semantic-idle-breadcrumbs-separator
  1137. 'mode-specific)
  1138. (semantic-analyze-unsplit-name format-pieces))
  1139. ;; Custom separator.
  1140. ((stringp semantic-idle-breadcrumbs-separator)
  1141. (mapconcat
  1142. #'identity
  1143. format-pieces
  1144. semantic-idle-breadcrumbs-separator)))))
  1145. complete-format)
  1146. )
  1147. (defun semantic-idle-breadcrumbs--format-innermost-first
  1148. (tag-list &optional max-length)
  1149. "Format TAG-LIST placing the innermost tag first, separated from its parents.
  1150. If MAX-LENGTH is non-nil, the innermost tag is shortened."
  1151. (let* (;; Separate and format remaining tags. Calculate length of
  1152. ;; resulting string.
  1153. (rest-tags (butlast tag-list))
  1154. (rest-format (if rest-tags
  1155. (concat
  1156. " | "
  1157. (semantic-idle-breadcrumbs--format-linear
  1158. rest-tags))
  1159. ""))
  1160. (rest-length (length rest-format))
  1161. ;; Format innermost tag and calculate length of resulting
  1162. ;; string.
  1163. (inner-format (semantic-idle-breadcrumbs--format-tag
  1164. (car (last tag-list))
  1165. #'semantic-format-tag-prototype))
  1166. (inner-length (length inner-format))
  1167. ;; Calculate complete length and shorten string for innermost
  1168. ;; tag if MAX-LENGTH is non-nil and the complete string is
  1169. ;; too long.
  1170. (complete-length (+ inner-length rest-length))
  1171. (inner-short (if (and max-length
  1172. (<= complete-length max-length))
  1173. inner-format
  1174. (concat (substring
  1175. inner-format
  1176. 0
  1177. (- inner-length
  1178. (- complete-length max-length)
  1179. 4))
  1180. " ..."))))
  1181. ;; Concat both parts.
  1182. (concat inner-short rest-format))
  1183. )
  1184. (defun semantic-idle-breadcrumbs--format-tag (tag &optional format-function)
  1185. "Format TAG using the configured function or FORMAT-FUNCTION.
  1186. This function also adds text properties for help-echo, mouse
  1187. highlighting and a keymap."
  1188. (let ((formatted (funcall
  1189. (or format-function
  1190. semantic-idle-breadcrumbs-format-tag-function)
  1191. tag nil t)))
  1192. (add-text-properties
  1193. 0 (length formatted)
  1194. (list
  1195. 'tag
  1196. tag
  1197. 'help-echo
  1198. (format
  1199. "Tag %s
  1200. Type: %s
  1201. mouse-1: jump to tag
  1202. mouse-3: popup context menu"
  1203. (semantic-tag-name tag)
  1204. (semantic-tag-class tag))
  1205. 'mouse-face
  1206. 'highlight
  1207. 'keymap
  1208. semantic-idle-breadcrumbs-popup-map)
  1209. formatted)
  1210. formatted))
  1211. (provide 'semantic/idle)
  1212. ;; Local variables:
  1213. ;; generated-autoload-file: "loaddefs.el"
  1214. ;; generated-autoload-load-name: "semantic/idle"
  1215. ;; End:
  1216. ;;; semantic/idle.el ends here