Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

596 lines
24 KiB

  1. ;;; clipmon.el --- Clipboard monitor - watch system clipboard, add changes to kill ring/autoinsert
  2. ;;
  3. ;; Copyright (c) 2015-2016 Brian Burns
  4. ;;
  5. ;; Author: Brian Burns <bburns.km@gmail.com>
  6. ;; URL: https://github.com/bburns/clipmon
  7. ;; Keywords: convenience
  8. ;; Version: 20160925
  9. ;;
  10. ;; This package is NOT part of GNU Emacs.
  11. ;;
  12. ;; This program is free software; you can redistribute it and/or modify
  13. ;; it under the terms of the GNU General Public License as published by
  14. ;; the Free Software Foundation, either version 3 of the License, or
  15. ;; (at your option) any later version.
  16. ;;
  17. ;; This program is distributed in the hope that it will be useful,
  18. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ;; GNU General Public License for more details.
  21. ;;
  22. ;; You should have received a copy of the GNU General Public License
  23. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. ;;
  25. ;;
  26. ;;; Commentary:
  27. ;;
  28. ;;;; Description
  29. ;; ----------------------------------------------------------------------------
  30. ;;
  31. ;; Clipmon is a clipboard monitor - it watches the system clipboard and can
  32. ;; automatically insert any new text into the current location in Emacs.
  33. ;;
  34. ;; It also adds changes to the system clipboard to the kill ring, making Emacs
  35. ;; into a clipboard manager for text - you can then use a package like
  36. ;; browse-kill-ring or helm-ring to view and manage your clipboard history.
  37. ;;
  38. ;; **Warning (2015-12-24): in an X-windows system with clipmon-mode on, bringing
  39. ;; up a graphical menu (e.g. Shift+Mouse-1) will cause Emacs to hang. See
  40. ;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22214.
  41. ;; X-windows starts a timer when checking the contents of the clipboard, which
  42. ;; interferes with the clipmon timer.**
  43. ;;
  44. ;; Update (2016-01-27): in an X-windows system, Clipmon now uses the clipboard
  45. ;; instead of the primary selection - see https://github.com/bburns/clipmon/issues/4.
  46. ;;
  47. ;; You can use Clipmon for taking notes from a webpage, for example - just copy the
  48. ;; text you want to save and it will be added to Emacs. It helps to have an
  49. ;; autocopy feature or addon for the browser, e.g. AutoCopy 2 for Firefox - then
  50. ;; you can just select text to add it to Emacs.
  51. ;;
  52. ;; Here's a diagram - text flows from the top to the bottom:
  53. ;;
  54. ;; +---------------------+
  55. ;; | Other programs |+
  56. ;; +---------------------+|
  57. ;; +---------------------+
  58. ;; /
  59. ;; +-----------+
  60. ;; | System |
  61. ;; | clipboard |
  62. ;; +-----------+
  63. ;; OS /
  64. ;; ---------------------------------------------------
  65. ;; Emacs /
  66. ;; /
  67. ;; +--------------+ +---------------+
  68. ;; | clipmon-mode |......| autoinsert |
  69. ;; +--------------+ +---------------+
  70. ;; | .
  71. ;; +-----------+ .
  72. ;; | Emacs ++ .
  73. ;; | kill ring ++ +--------------+
  74. ;; +-----------+|+ | transforms |
  75. ;; +-----------+| +--------------+
  76. ;; +-----------+ .
  77. ;; | .
  78. ;; | yank . autoinsert
  79. ;; +--------------------------+
  80. ;; | Emacs buffer |
  81. ;; +--------------------------+
  82. ;;
  83. ;;
  84. ;; The solid line is turned on and off with `clipmon-mode', while the dotted
  85. ;; line is turned on and off with `clipmon-autoinsert-toggle', usually bound to a key.
  86. ;; There are also various transformations you can perform on the text, e.g.
  87. ;; adding newlines to the end.
  88. ;;
  89. ;; (Emacs's kill-ring is like the system clipboard but with multiple items in
  90. ;; it. If you copy a bunch of things in another program, Emacs normally only
  91. ;; knows about the last one copied, but with clipmon mode on, it will monitor
  92. ;; the system clipboard and add any new text it sees to the kill ring.)
  93. ;;
  94. ;;
  95. ;;;; Installation
  96. ;; ----------------------------------------------------------------------------
  97. ;;
  98. ;; It's simplest to use the package manager:
  99. ;;
  100. ;; M-: (package-install 'clipmon)
  101. ;;
  102. ;; It will then be ready to use, and will also be available the next time you
  103. ;; start Emacs.
  104. ;;
  105. ;;
  106. ;;;; Usage
  107. ;; ----------------------------------------------------------------------------
  108. ;;
  109. ;; To give it a try, do M-: (clipmon-autoinsert-toggle) - this will turn on
  110. ;; autoinsert. Then go to another application and copy some text to the
  111. ;; clipboard - clipmon should detect it after a second or two and make a beep.
  112. ;; If you switch back to Emacs, the text should be there in your buffer.
  113. ;;
  114. ;; Note that you can still yank and pull text in Emacs as usual while autoinsert
  115. ;; is on, since it only monitors the system clipboard.
  116. ;;
  117. ;; You can turn off autoinsert with the same command - to add a keybinding to it
  118. ;; add something like this to your init file:
  119. ;;
  120. ;; (global-set-key (kbd "<M-f2>") 'clipmon-autoinsert-toggle)
  121. ;;
  122. ;; You can also turn it on and off from the Options menu.
  123. ;;
  124. ;; Also, if no change is detected after a certain number of minutes, autoinsert will
  125. ;; turn itself off automatically with another beep. This is so you don't forget
  126. ;; that autoinsert is on and accidentally add text to your buffer.
  127. ;;
  128. ;; And note: if you happen to copy the same text to the clipboard twice, clipmon
  129. ;; won't know about the second time, as it only detects changes. And if you copy
  130. ;; text faster than the timer interval is set it may miss some changes, but you
  131. ;; can adjust the interval.
  132. ;;
  133. ;;
  134. ;;;; Using as a clipboard manager
  135. ;; ----------------------------------------------------------------------------
  136. ;;
  137. ;; To try out clipmon as a clipboard manager, make sure clipmon-mode is on by
  138. ;; doing M-: (clipmon-mode 1) (also accessible from the Options menu) and that
  139. ;; autoinsert is off, then copy a few pieces of text from another program (more
  140. ;; slowly than the default timer interval of 2 seconds though). Switch back to
  141. ;; Emacs, and see that you can yank any of the text back with C-y, M-y, M-y...
  142. ;;
  143. ;; Note that when you turn on autoinsert, it also turns on clipmon-mode, to
  144. ;; capture text to the kill ring, but if you'd like to turn on clipmon-mode
  145. ;; automatically, you can add this to your init file:
  146. ;;
  147. ;; ;; monitor the system clipboard and add any changes to the kill ring
  148. ;; (add-to-list 'after-init-hook 'clipmon-mode-start)
  149. ;;
  150. ;; You can also use the package browse-kill-ring to manage the kill ring - you
  151. ;; can install it with M-: (package-install 'browse-kill-ring), then call
  152. ;; `browse-kill-ring' to see the contents of the kill ring, insert from it,
  153. ;; delete items, etc. Helm also has a package called helm-ring, with the
  154. ;; function `helm-show-kill-ring'.
  155. ;;
  156. ;; You can persist the kill ring between sessions if you'd like (though note
  157. ;; that this might involve writing sensitive information like passwords to the
  158. ;; disk - although you could always delete such text from the kill ring with
  159. ;; `browse-kill-ring-delete'). To do so, add this to your init file:
  160. ;;
  161. ;; ;; persist the kill ring between sessions
  162. ;; (add-to-list 'after-init-hook 'clipmon-persist)
  163. ;;
  164. ;; This will use Emacs's savehist library to save the kill ring, both at the end
  165. ;; of the session and at set intervals. However, savehist also saves various
  166. ;; other settings by default, including the minibuffer history - see
  167. ;; `savehist-mode' for more details. To change the autosave interval, add
  168. ;; something like this:
  169. ;;
  170. ;; (setq savehist-autosave-interval (* 5 60)) ; save every 5 minutes (default)
  171. ;;
  172. ;; The kill ring has a fixed number of entries which you can set, depending on
  173. ;; how much history you want to save between sessions:
  174. ;;
  175. ;; (setq kill-ring-max 500) ; default is 60 in Emacs 24.4
  176. ;;
  177. ;; To see how much space the kill-ring is taking up, you can call this function:
  178. ;;
  179. ;; (clipmon-kill-ring-total)
  180. ;; => 29670 characters
  181. ;;
  182. ;;
  183. ;;;; Options
  184. ;; ----------------------------------------------------------------------------
  185. ;;
  186. ;; There are various options you can set with customize:
  187. ;;
  188. ;; (customize-group 'clipmon)
  189. ;;
  190. ;; or set them in your init file - these are the default values:
  191. ;;
  192. ;; (setq clipmon-timer-interval 2) ; check system clipboard every n secs
  193. ;; (setq clipmon-autoinsert-sound t) ; t for included beep, or path or nil
  194. ;; (setq clipmon-autoinsert-color "red") ; color of cursor when autoinsert is on
  195. ;; (setq clipmon-autoinsert-timeout 5) ; stop autoinsert after n mins inactivity
  196. ;;
  197. ;; before inserting the text, transformations are performed on it in this order:
  198. ;;
  199. ;; (setq clipmon-transform-trim t) ; remove leading whitespace
  200. ;; (setq clipmon-transform-remove ; remove text matching this regexp
  201. ;; "\\[[0-9][0-9]?[0-9]?\\]\\|\\[citation needed\\]\\|\\[by whom?\\]")
  202. ;; (setq clipmon-transform-prefix "") ; add to start of text
  203. ;; (setq clipmon-transform-suffix "\n\n") ; add to end of text
  204. ;; (setq clipmon-transform-function nil) ; additional transform function
  205. ;;
  206. ;;
  207. ;;;; Todo
  208. ;; ----------------------------------------------------------------------------
  209. ;;
  210. ;; - Prefix with C-u to set a target point, then allow cut/copy/pasting from
  211. ;; within Emacs, eg to take notes from another buffer, or move text elsewhere.
  212. ;;
  213. ;;
  214. ;;; Code:
  215. ;;;; Renamings
  216. ;; ----------------------------------------------------------------------------
  217. ;; just renaming some things here - must come before defcustoms.
  218. ;; could remove after some time though.
  219. (eval-when-compile ; because it's a macro
  220. (defalias 'clipmon--rename 'define-obsolete-variable-alias))
  221. ;; rename old to new
  222. (clipmon--rename 'clipmon-interval 'clipmon-timer-interval "20150211")
  223. (clipmon--rename 'clipmon-cursor-color 'clipmon-autoinsert-color "20150211")
  224. (clipmon--rename 'clipmon-sound 'clipmon-autoinsert-sound "20150211")
  225. (clipmon--rename 'clipmon-timeout 'clipmon-autoinsert-timeout "20150211")
  226. (clipmon--rename 'clipmon-trim 'clipmon-transform-trim "20150211")
  227. (clipmon--rename 'clipmon-remove-regexp 'clipmon-transform-remove "20150211")
  228. (clipmon--rename 'clipmon-prefix 'clipmon-transform-prefix "20150211")
  229. (clipmon--rename 'clipmon-suffix 'clipmon-transform-suffix "20150211")
  230. ;; FIXME how just mark as obsolete/removed?
  231. (clipmon--rename 'clipmon-action 'clipmon-action-obsolete "20150211")
  232. ;;;; Public settings
  233. ;; ----------------------------------------------------------------------------
  234. (defgroup clipmon nil
  235. "Clipboard monitor - add clipboard contents to kill ring and automatically insert."
  236. :group 'convenience
  237. :group 'killing)
  238. (defcustom clipmon-timer-interval 2
  239. "Interval for checking system clipboard for changes, in seconds."
  240. :group 'clipmon
  241. :type 'integer)
  242. (defcustom clipmon-autoinsert-color "red"
  243. "Color to set cursor when clipmon autoinsert is on. Set to nil for no change."
  244. :group 'clipmon
  245. :type 'color)
  246. (defcustom clipmon-autoinsert-sound t
  247. "Path to sound file to play on autoinsert, t for included file, or nil.
  248. Use t for the included sound file (see
  249. `clipmon--included-sound-file'), nil for no sound, or path to an
  250. audio file - Emacs can play .wav or .au files."
  251. ; Note: can't use `ding' here because it doesn't make a sound when Emacs
  252. ; doesn't have focus.
  253. :group 'clipmon
  254. :type '(radio
  255. (string :tag "Audio file (.wav or .au)")
  256. (boolean :tag "Included sound file")))
  257. (defcustom clipmon-autoinsert-timeout 5
  258. "Stop autoinsert if no system clipboard activity after this many minutes.
  259. Set to nil for no timeout."
  260. :group 'clipmon
  261. :type 'integer)
  262. ;; transforms on text - these are performed in this order
  263. (defcustom clipmon-transform-trim t
  264. "If non-nil, remove leading whitespace from string before autoinserting.
  265. Often it's hard to select text without grabbing a leading space,
  266. so this will remove it."
  267. :group 'clipmon
  268. :type 'boolean)
  269. (defcustom clipmon-transform-remove
  270. "\\[[0-9][0-9]?[0-9]?\\]\\|\\[citation needed\\]\\|\\[by whom?\\]"
  271. "Any text matching this regexp will be removed before autoinserting.
  272. e.g. Wikipedia-style references with 1-3 digits - [3], [115]."
  273. :group 'clipmon
  274. :type 'regexp)
  275. (defcustom clipmon-transform-prefix ""
  276. "String to add to start of clipboard contents before autoinserting."
  277. :group 'clipmon
  278. :type 'string)
  279. (defcustom clipmon-transform-suffix "\n\n"
  280. "String to add to end of clipboard contents before autoinserting.
  281. Default is two newlines, which leaves a blank line between clips.
  282. \(To add a newline in the customize interface, type \\[quoted-insert] C-j)."
  283. :group 'clipmon
  284. :type 'string)
  285. (defcustom clipmon-transform-function nil
  286. "Function to perform additional transformations on text before autoinserting.
  287. Receives one argument, the clipboard text - should return the changed text.
  288. E.g. to make the text lowercase before pasting,
  289. (setq clipmon-transform-function (lambda (s) (downcase s)))"
  290. :group 'clipmon
  291. :type 'function
  292. :risky t)
  293. ;;;; Initialize
  294. ;; ----------------------------------------------------------------------------
  295. ; add items to Options menu
  296. ;;;###autoload
  297. (define-key-after global-map [menu-bar options clipmon-separator] ; path to new item
  298. '(menu-item "---")
  299. 'highlight-paren-mode) ; add after this
  300. ;;;###autoload
  301. (define-key-after global-map [menu-bar options clipmon-killring] ; path to new item
  302. '(menu-item "Clipboard Monitor (Add to Kill Ring)"
  303. clipmon-mode ; function to call on click
  304. :help "Add changes to the system clipboard to Emacs's kill ring."
  305. :button (:toggle . clipmon-mode)) ; show checkmark on/off
  306. 'clipmon-separator) ; add after this
  307. ;;;###autoload
  308. (define-key-after global-map [menu-bar options clipmon-autoinsert] ; path to new item
  309. '(menu-item "Clipboard Monitor Autoinsert"
  310. clipmon-autoinsert-toggle ; function to call on click
  311. :help "Automatically insert changes to the system clipboard at the current location."
  312. :button (:toggle . clipmon--autoinsert)) ; show checkmark on/off
  313. 'clipmon-killring) ; add after this
  314. ;;;; Private variables
  315. ;; ----------------------------------------------------------------------------
  316. (defvar clipmon--timer nil
  317. "Timer handle for clipboard monitor to watch system clipboard.")
  318. (defvar clipmon--autoinsert nil
  319. "Non-nil if autoinsert is on.")
  320. (defvar clipmon--autoinsert-timeout-start nil
  321. "Time that autoinsert timeout timer was started.")
  322. (defvar clipmon--previous-contents nil
  323. "Last contents of the system clipboard.")
  324. (defvar clipmon--cursor-color-original nil
  325. "Original cursor color.")
  326. (defconst clipmon--folder
  327. (file-name-directory (or load-file-name (file-name-directory (buffer-file-name))))
  328. "Path to clipmon install folder, or current buffer's location.")
  329. (defconst clipmon--included-sound-file
  330. (expand-file-name "clipmon.wav" clipmon--folder)
  331. "Path to included audio file.")
  332. ;;;; Public functions
  333. ;; ----------------------------------------------------------------------------
  334. ;;;###autoload
  335. (define-minor-mode clipmon-mode
  336. "Start/stop clipboard monitor - watch system clipboard, add changes to kill ring.
  337. To also insert the changes to the system clipboard at the current
  338. location, call `clipmon-autoinsert-toggle' to turn autoinsert on
  339. and off. See commentary in source file for more information -
  340. M-: (find-library 'clipmon).
  341. Upgrade note (2015-02-11): you'll need to bind your shortcut key to
  342. `clipmon-autoinsert-toggle' instead of `clipmon-mode'."
  343. :global t
  344. :lighter ""
  345. ; value of clipmon-mode is toggled before this implicitly
  346. (if clipmon-mode (clipmon-mode-start) (clipmon-mode-stop)))
  347. ;;;###autoload
  348. (defun clipmon-mode-start ()
  349. "Start clipboard monitor - watch system clipboard, add changes to kill ring."
  350. (interactive)
  351. (setq clipmon-mode t) ; in case called outside of clipmon-mode fn
  352. (unless clipmon--timer
  353. (setq clipmon--previous-contents (clipmon--clipboard-contents))
  354. (setq clipmon--timer
  355. (run-at-time nil clipmon-timer-interval 'clipmon--check-clipboard))
  356. (message "Clipboard monitor started - watching system clipboard, adding changes to kill ring.")
  357. ))
  358. (defun clipmon-mode-stop ()
  359. "Stop clipboard monitor and autoinsert modes."
  360. (interactive)
  361. (setq clipmon-mode nil) ; in case called outside of clipmon-mode fn
  362. (when clipmon--timer
  363. (cancel-timer clipmon--timer)
  364. (setq clipmon--timer nil)
  365. (if clipmon--autoinsert (clipmon-autoinsert-stop)) ; turn off autoinsert also
  366. (message "Clipboard monitor stopped.")
  367. ))
  368. ;;;###autoload
  369. (defun clipmon-autoinsert-toggle ()
  370. "Turn autoinsert on/off - watch system clipboard and insert changes.
  371. Will change cursor color and play a sound. Text will be
  372. transformed before insertion according to various settings - see
  373. `clipmon--transform-text'."
  374. (interactive)
  375. ;; note: a minor mode would toggle the value here rather than in the fns
  376. (if clipmon--autoinsert (clipmon-autoinsert-stop) (clipmon-autoinsert-start)))
  377. (defun clipmon-autoinsert-start ()
  378. "Turn on autoinsert - change cursor color, play sound, insert changes."
  379. (interactive)
  380. (if (null clipmon--timer) (clipmon-mode-start)) ; make sure clipmon is on
  381. (if clipmon--autoinsert
  382. (message "Clipboard monitor autoinsert already on.")
  383. (setq clipmon--autoinsert-timeout-start (current-time))
  384. (when clipmon-autoinsert-color
  385. (setq clipmon--cursor-color-original (face-background 'cursor))
  386. (set-face-background 'cursor clipmon-autoinsert-color))
  387. (message
  388. "Clipboard monitor autoinsert started with timer interval %g seconds. Stop with %s."
  389. clipmon-timer-interval
  390. (substitute-command-keys "\\[clipmon-autoinsert-toggle]")) ; eg "<M-f2>"
  391. (clipmon--play-sound)
  392. (setq clipmon--autoinsert t)
  393. ))
  394. (defun clipmon-autoinsert-stop (&optional msg)
  395. "Turn off autoinsert - restore cursor color and play sound.
  396. Show optional message MSG, or default message."
  397. (interactive)
  398. (if (null clipmon--autoinsert)
  399. (message "Clipboard monitor autoinsert already off.")
  400. (if clipmon--cursor-color-original
  401. (set-face-background 'cursor clipmon--cursor-color-original))
  402. (message (or msg "Clipboard monitor autoinsert stopped."))
  403. (clipmon--play-sound)
  404. (setq clipmon--autoinsert nil)
  405. ))
  406. ;;;###autoload
  407. (defun clipmon-persist ()
  408. "Persist the kill ring to disk using Emacs's savehist library.
  409. Will save the kill ring at the end of the session and at various
  410. intervals as specified by variable `savehist-autosave-interval'.
  411. Note that savehist also includes various other Emacs settings by
  412. default, including the minibuffer history - see function
  413. `savehist-mode' for more details."
  414. (require 'savehist)
  415. (defvar savehist-additional-variables) ; for compiler warning
  416. (add-to-list 'savehist-additional-variables 'kill-ring)
  417. (savehist-mode 1))
  418. ;;;; Private functions
  419. ;; ----------------------------------------------------------------------------
  420. (defun clipmon--check-clipboard ()
  421. "Check the clipboard and call `clipmon--on-clipboard-change' if changed.
  422. Otherwise check autoinsert idle timer and stop if it's been idle a while."
  423. (let ((s (clipmon--clipboard-contents))) ; s may actually be nil here
  424. (if (and s (not (string-equal s clipmon--previous-contents))) ; if not nil, and changed
  425. (clipmon--on-clipboard-change s) ; add to kill-ring, autoinsert
  426. ;; otherwise stop autoinsert if clipboard has been idle a while
  427. (if (and clipmon--autoinsert clipmon-autoinsert-timeout)
  428. (let ((idle-seconds (clipmon--seconds-since clipmon--autoinsert-timeout-start)))
  429. (when (>= idle-seconds (* 60 clipmon-autoinsert-timeout))
  430. (clipmon-autoinsert-stop (format
  431. "Clipboard monitor autoinsert stopped after %g minutes of inactivity."
  432. clipmon-autoinsert-timeout))
  433. ))))))
  434. (defun clipmon--on-clipboard-change (s)
  435. "Clipboard changed - add text S to kill ring, and optionally insert it."
  436. (setq clipmon--previous-contents s) ; save contents
  437. (kill-new s) ; add to kill ring
  438. (when clipmon--autoinsert
  439. (setq s (clipmon--autoinsert-transform-text s))
  440. (insert s)
  441. (undo-boundary) ; mark a boundary between undo units
  442. (clipmon--play-sound)
  443. (setq clipmon--autoinsert-timeout-start (current-time)))) ; reset timeout
  444. (defun clipmon--autoinsert-transform-text (s)
  445. "Apply autoinsert transformations to clipboard text S."
  446. (if clipmon-transform-trim (setq s (clipmon--trim-left s)))
  447. (if clipmon-transform-remove
  448. (setq s (replace-regexp-in-string clipmon-transform-remove "" s)))
  449. (if clipmon-transform-prefix (setq s (concat clipmon-transform-prefix s)))
  450. (if clipmon-transform-suffix (setq s (concat s clipmon-transform-suffix)))
  451. (if clipmon-transform-function (setq s (funcall clipmon-transform-function s)))
  452. s)
  453. (defun clipmon--play-sound ()
  454. "Play a user-specified sound file, the included sound file, or nothing."
  455. (if clipmon-autoinsert-sound
  456. (if (stringp clipmon-autoinsert-sound)
  457. ;; play-sound-file can throw an error if no sound device found
  458. (ignore-errors (play-sound-file clipmon-autoinsert-sound))
  459. (ignore-errors (play-sound-file clipmon--included-sound-file)))))
  460. ;;;; Library functions
  461. ;; ----------------------------------------------------------------------------
  462. (defun clipmon-kill-ring-total ()
  463. "Get total size of kill ring, in characters."
  464. (let ((sum 0))
  465. (mapc (lambda (s) (setq sum (+ sum (length s)))) kill-ring) sum))
  466. (defun clipmon--remove-properties (s)
  467. "Remove formatting properties from string S."
  468. (if (null s) nil
  469. (substring-no-properties s)))
  470. (defun clipmon--get-selection ()
  471. "Get the clipboard contents"
  472. ;; Note: When the OS is first started these functions will throw
  473. ;; (error "No selection is available"), so need to ignore errors.
  474. (cond ((boundp 'mac-carbon-version-string) ; emacs mac port
  475. ;; Need to have this before emacs25 since `gui-get-selection' is also
  476. ;; bound in the mac port, but it doesn't work right
  477. (ignore-errors (funcall interprogram-paste-function)))
  478. ((fboundp 'gui-get-selection) ; emacs25
  479. ; better to (setq selection-coding-system 'utf-8) to handle chinese,
  480. ; which is the default value for gui-get-selection etc
  481. ; because windows needs STRING. same below.
  482. ; (ignore-errors (gui-get-selection 'CLIPBOARD 'UTF8_STRING)))
  483. (ignore-errors (gui-get-selection 'CLIPBOARD))) ; for windows needs STRING
  484. ((eq window-system 'w32) ; windows/emacs24
  485. ;; Note: (x-get-selection 'CLIPBOARD) doesn't work on Windows.
  486. (ignore-errors (x-get-selection-value))) ; can be nil
  487. (t ; linux+osx/emacs24
  488. ; (ignore-errors (x-get-selection 'CLIPBOARD 'UTF8_STRING)))))
  489. (ignore-errors (x-get-selection 'CLIPBOARD)))))
  490. (defun clipmon--clipboard-contents ()
  491. "Get current contents of system clipboard - returns a string, or nil."
  492. ;;. do we really need to remove the text properties?
  493. (let ((text (clipmon--remove-properties (clipmon--get-selection)))
  494. (top-of-kill-ring (clipmon--remove-properties (car kill-ring))))
  495. (cond ((null text) nil)
  496. ;; don't return the text if user just copied/cut it from emacs
  497. ((string= text top-of-kill-ring) nil)
  498. (t text))))
  499. (defun clipmon--trim-left (s)
  500. "Remove leading spaces from string S."
  501. (replace-regexp-in-string "^[ \t]+" "" s))
  502. (defun clipmon--seconds-since (time)
  503. "Return number of seconds elapsed since the given TIME.
  504. TIME should be in Emacs time format (see `current-time').
  505. Includes approximate number of milliseconds also.
  506. Valid for up to 2**16 seconds = 65536 secs ~ 18hrs."
  507. (let* ((elapsed (time-subtract (current-time) time))
  508. (seconds (nth 1 elapsed))
  509. (microseconds (nth 2 elapsed)) ; accurate to milliseconds on my system, anyway
  510. (total (+ seconds (/ microseconds 1.0e6))))
  511. total))
  512. ;;;; Footer
  513. ;; ----------------------------------------------------------------------------
  514. (provide 'clipmon)
  515. ;; Local Variables:
  516. ;; indent-tabs-mode: nil
  517. ;; End:
  518. ;;; clipmon.el ends here