| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970 | ;;; org-mouse.el --- Better mouse support for org-mode;; Copyright (c) 2006 Piotr Zielinski;;;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com>;; Version: 0.21;; $Id: org-mouse.el 347 2006-11-12 23:57:50Z pz215 $;; ;; The latest version of this file is available from;;;; http://www.cl.cam.ac.uk/~pz215/files/org-mouse.el;;;; This file is *NOT* part of GNU Emacs.;; This file is distributed under the same terms as GNU Emacs.;; This program is free software; you can redistribute it and/or;; modify it under the terms of the GNU General Public License as;; published by the Free Software Foundation; either version 2 of;; the License, or (at your option) any later version.;; This program is distributed in the hope that it will be;; useful, but WITHOUT ANY WARRANTY; without even the implied;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR;; PURPOSE.  See the GNU General Public License for more details.;; You should have received a copy of the GNU General Public;; License along with this program; if not, write to the Free;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,;; MA 02111-1307 USA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Commentary:;;;; Org-mouse provides better mouse support for org-mode.  Org-mode is;; a mode for keeping notes, maintaining ToDo lists, and doing project;; planning with a fast and effective plain-text system.  It is;; available from;;;; http://staff.science.uva.nl/~dominik/Tools/org/;;;; Org-mouse implements the following features:;; * following links with the left mouse button (in Emacs 22);; * subtree expansion/collapse (org-cycle) with the left mouse button;; * several context menus on the right mouse button:;;    + general text;;    + headlines;;    + timestamps;;    + priorities;;    + links;;    + tags;; * promoting/demoting/moving subtrees with mouse-3;;    + if the drag starts and ends in the same line then promote/demote;;    + otherwise move the subtree ;; * date/time extraction from selected text (requires a python script);;   (eg. select text from your email and click "Add Appointment");;;; The python script that automatically extracts date/time information;; from a piece of English text is available from:;;;; http://www.cl.cam.ac.uk/~pz215/files/timeparser.py;;;; Use;; ------------;;;; To use this package, put the following line in your .emacs:;;;;    (require 'org-mouse);;;; Tested with Emacs 22.0.50, org-mode 4.33;; Fixme:;; + deal with folding / unfolding issues;; TODO (This list is only theoretical, if you'd like to have some;; feature implemented or a bug fix please send me an email, even if;; something similar appears in the list below.  This will help me get;; the priorities right.):;;;; + org-store-link, insert link;; + org tables;; + occur with the current word/tag (same menu item);; + ctrl-c ctrl-c, for example, renumber the current list;; + internal links;; Please email me with new feature suggestions / bugs;; History:;;;; Version 0.21;; + selected text activates its context menu;; + shift-middleclick or right-drag inserts the text from the clipboard in the form of a link;;;; Version 0.20;; + the new "TODO Status" submenu replaces the "Cycle TODO" menu item ;; + the TODO menu can now list occurrences of a specific TODO keyword;; + #+STARTUP line is now recognized;;;; Version 0.19;; + added support for dragging URLs to the org-buffer;;;; Version 0.18;; + added support for agenda blocks;;;; Version 0.17;; + toggle checkboxes with a single click;;;; Version 0.16;; + added support for checkboxes;;;; Version 0.15;; + org-mode now works with the Agenda buffer as well;;;; Version 0.14;; + added a menu option that converts plain list items to outline items;;;; Version 0.13 ;; + "Insert Heading" now inserts a sibling heading if the point is;;   on "***" and a child heading otherwise;; ;; Version 0.12;; + compatible with Emacs 21;; + custom agenda commands added to the main menu;; + moving trees should now work between windows in the same frame;;;; Version 0.11;; + fixed org-mouse-at-link (thanks to Carsten);; + removed [follow-link] bindings;;;; Version 0.10;; + added a menu option to remove highlights;; + compatible with org-mode 4.21 now;;;; Version 0.08: ;; + trees can be moved/promoted/demoted by dragging with the right;;   mouse button (mouse-3);; + small changes in the above function;;;; Versions 0.01 -- 0.07: (I don't remember)(eval-when-compile (require 'cl))(defvar org-mouse-plain-list-regexp "\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) ")(defvar org-mouse-direct t)(defgroup org-mouse nil  "Org-mouse"  :tag "Org Mouse."  :group 'org)(defcustom org-mouse-punctuation ":"  ""  :group 'org-mouse  :type 'string)(defun org-mouse-re-search-line (regexp)  "Searches the current line for a given regular expression."  (beginning-of-line)  (re-search-forward regexp (point-at-eol) t))(defun org-mouse-end-headline ()  "Go to the end of current headline (ignoring tags)."  (interactive)  (end-of-line)  (skip-chars-backward "\t ")  (when (looking-back ":[A-Za-z]+:")    (skip-chars-backward ":A-Za-z")    (skip-chars-backward "\t ")))(defun org-mouse-show-context-menu (event prefix)  (interactive "@e \nP")  (if (and (= (event-click-count event) 1)	   (or (not mark-active) 	       (sit-for (/ double-click-time 1000.0))))      (progn 	(select-window (posn-window (event-start event)))	(when (not (org-mouse-mark-active))	  (goto-char (posn-point (event-start event)))	  (when (not (eolp)) (save-excursion (run-hooks 'post-command-hook)))	  (let ((redisplay-dont-pause t))	    (sit-for 0)))	(if (functionp org-mouse-context-menu-function)	    (funcall org-mouse-context-menu-function event)	  (mouse-major-mode-menu event prefix))	)    (setq this-command 'mouse-save-then-kill)    (mouse-save-then-kill event)))(defun org-mouse-line-position ()  "Returns :beginning :middle :end"  (cond   ((eolp) :end)   ((org-mouse-bolp) :begin)   (t :middle)))(defun org-mouse-empty-line ()  (save-excursion (beginning-of-line) (looking-at "[ \t]*$")))(defun org-mouse-next-heading ()  "Goes to the next heading and if there is none, it ensures that the point is at the beginning of an empty line."  (unless (outline-next-heading)    (beginning-of-line)    (unless (org-mouse-empty-line)      (end-of-line)      (newline))))(defun org-mouse-insert-heading ()  (interactive)  (case (org-mouse-line-position)    (:begin (beginning-of-line)	    (org-insert-heading))    (t (org-mouse-next-heading)       (org-insert-heading))))(defun org-mouse-timestamp-today (&optional shift units)   (interactive)  (flet ((org-read-date (x &optional y) (current-time)))     (org-time-stamp nil))  (when shift    (org-timestamp-change shift units)))(defun org-mouse-keyword-menu (keywords function &optional selected itemformat)  (message "kmenu: %S" selected)  (mapcar    `(lambda (keyword)      (vector (cond	      ((functionp ,itemformat) (funcall ,itemformat keyword))	      ((stringp ,itemformat) (format ,itemformat keyword))	      (t keyword))	     (list 'funcall ,function keyword)	     :style (cond 		     ((null ,selected) t)		     ((functionp ,selected) 'toggle)		     (t 'radio))	     :selected (if (functionp ,selected) 			   (and (funcall ,selected keyword) t)			 (equal ,selected keyword))))    keywords))     (defun org-mouse-remove-match-and-spaces ()  (interactive)  (replace-match "")  (just-one-space))(defun org-mouse-replace-match-and-surround (newtext &optional fixedcase 						     literal string subexp)  "The same as replace-match, but surrounds the replacement with spaces."  (apply 'replace-match rest)  (save-excursion    (goto-char (match-beginning (or subexp 0)))     (just-one-space)    (goto-char (match-end (or subexp 0)))     (just-one-space)))  (defun org-mouse-keyword-replace-menu (keywords &optional group itemformat)  (setq group (or group 0))  (let ((replace (org-mouse-match-closure 		  'org-mouse-replace-match-and-surround)))    (append     (org-mouse-keyword-menu       keywords      `(lambda (keyword) (funcall ,replace keyword t t nil ,group))      (match-string group)      itemformat)     `(["None" org-mouse-remove-match-and-spaces 	:style radio	:selected ,(not (member (match-string group) keywords))]))))     (defvar org-mouse-context-menu-function nil)(make-variable-buffer-local 'org-mouse-context-menu-function)(defun org-mouse-show-headlines ()  (interactive)   (let ((this-command 'org-cycle) 	(last-command 'org-cycle)	(org-cycle-global-status nil))    (org-cycle '(4))    (org-cycle '(4))))(defun org-mouse-show-overview ()  (interactive)   (let ((org-cycle-global-status nil))    (org-cycle '(4))))(defun org-mouse-set-priority (priority)  (flet ((read-char-exclusive () priority))    (org-priority)))(defvar org-mouse-priority-regexp "\\[#\\([A-Z]\\)\\]"  "Regular expression matching the priority indicator.  Differs from `org-priority-regexp' in that it doesn't contain the leading '.*?'.")(defun org-mouse-get-priority (&optional default)  (save-excursion     (if (org-mouse-re-search-line org-mouse-priority-regexp)	(match-string 1)      (when default (char-to-string org-default-priority)))))(defun org-mouse-at-link ()  (and (eq (get-text-property (point) 'face) 'org-link)       (save-excursion         (goto-char (previous-single-property-change (point) 'face))         (or (looking-at org-bracket-link-regexp)             (looking-at org-angle-link-re)             (looking-at org-plain-link-re)))))(defun org-mouse-delete-timestamp ()  "Deletes the current timestamp as well as the precedingSCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:"  (when (or (org-at-date-range-p) (org-at-timestamp-p))    (replace-match "")			; delete the timestamp    (skip-chars-backward " :A-Z")    (when (looking-at " *[A-Z][A-Z]+:")      (replace-match ""))))(defun org-mouse-looking-at (regexp skipchars &optional movechars)   (save-excursion    (let ((point (point)))      (if (looking-at regexp) t	(skip-chars-backward skipchars)	(forward-char (or movechars 0))	(when (looking-at regexp)	  (> (match-end 0) point))))))	      (defun org-mouse-priority-list ()  (let ((ret) (current org-lowest-priority))    (while (>= current ?A)      (push (char-to-string current) ret)      (decf current))    ret))(defun org-mouse-tag-menu ()		;todo  (append   (let ((tags (org-split-string (org-get-tags) ":")))     (org-mouse-keyword-menu       (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)      `(lambda (tag) 	 (org-mouse-set-tags 	  (sort (if (member tag (quote ,tags)) 		    (delete tag (quote ,tags))		  (cons tag (quote ,tags)))		'string-lessp)))      `(lambda (tag) (member tag (quote ,tags)))      ))   '("--"     ["Align Tags Here" (org-set-tags nil t) t]     ["Align Tags in Buffer" (org-set-tags t t) t]     ["Set Tags ..." (org-set-tags) t])))   (defun org-mouse-set-tags (tags)  (save-excursion    ;; remove existing tags first    (beginning-of-line)    (when (org-mouse-re-search-line ":\\(\\([A-Za-z_]+:\\)+\\)")      (replace-match ""))    ;; set new tags if any    (when tags      (end-of-line)      (insert " :" (mapconcat 'identity tags ":") ":")      (org-set-tags nil t))))			  (defun org-mouse-insert-checkbox ()  (interactive)  (and (org-at-item-p)       (goto-char (match-end 0))       (unless (org-at-item-checkbox-p)	 (delete-horizontal-space)	 (insert " [ ] "))))(defun org-mouse-agenda-type (type)  (case type   ('tags "Tags: ")   ('todo "TODO: ")   ('tags-tree "Tags tree: ")   ('todo-tree "TODO tree: ")   ('occur-tree "Occur tree: ")   (t "Agenda command ???")))(defun org-mouse-list-options-menu (alloptions &optional function)  (let ((options (save-match-data 		   (split-string (match-string-no-properties 1)))))    (print options)    (loop for name in alloptions	  collect 	  (vector name 		  `(progn		     (replace-match 		      (mapconcat 'identity 				 (sort (if (member ',name ',options)					   (delete ',name ',options)					 (cons ',name ',options))				       'string-lessp)				 " ")		      nil nil nil 1)		     (when (functionp ',function) (funcall ',function)))		    :style 'toggle		    :selected (and (member name options) t)))))		    	    (defun org-mouse-clip-text (text maxlength)  (if (> (length text) maxlength)      (concat (substring text 0 (- maxlength 3)) "...")    text))(defun org-mouse-popup-global-menu ()  (popup-menu     `("Main Menu"     ["Show Overview" org-mouse-show-overview t]     ["Show Headlines" org-mouse-show-headlines t]     ["Show All" show-all t]     ["Remove Highlights" org-remove-occur-highlights      :visible org-occur-highlights]     "--"     ["Check Deadlines"       (if (functionp 'org-check-deadlines-and-todos)	  (org-check-deadlines-and-todos org-deadline-warning-days)	(org-check-deadlines org-deadline-warning-days)) t]     ["Check TODOs" org-show-todo-tree t]     ("Check Tags"       ,@(org-mouse-keyword-menu 	 (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)	 '(lambda (tag) (org-tags-sparse-tree nil tag)))      "--"      ["Custom Tag ..." org-tags-sparse-tree t])     ["Check Phrase ..." org-occur]     "--"     ["Display Agenda" org-agenda-list t]     ["Display Timeline" org-timeline t]     ["Display TODO List" org-todo-list t]     ("Display Tags"       ,@(org-mouse-keyword-menu 	 (sort (mapcar 'car (org-get-buffer-tags)) 'string-lessp)	 '(lambda (tag) (org-tags-view nil tag)))      "--"      ["Custom Tag ..." org-tags-view t])     ["Display Calendar" org-goto-calendar t]     "--"     ,@(org-mouse-keyword-menu 	(mapcar 'car org-agenda-custom-commands)	'(lambda (key) 	   (eval `(flet ((read-char-exclusive () (string-to-char ,key))) 		      (org-agenda nil))))	nil 	'(lambda (key)	   (let ((entry (assoc key org-agenda-custom-commands)))	     (org-mouse-clip-text 	      (cond	       ((stringp (nth 1 entry)) (nth 1 entry))	       ((stringp (nth 2 entry)) 		(concat (org-mouse-agenda-type (nth 1 entry))			(nth 2 entry)))	       (t "Agenda Command '%s'"))	      30))));; )     "--"     ["Delete Blank Lines" delete-blank-lines       :visible (org-mouse-empty-line)]     ["Insert Checkbox" org-mouse-insert-checkbox      :visible (and (org-at-item-p) (not (org-at-item-checkbox-p)))]     ["Insert Checkboxes"       (org-mouse-for-each-item 'org-mouse-insert-checkbox)      :visible (and (org-at-item-p) (not (org-at-item-checkbox-p)))]     ["Plain List to Outline" org-mouse-transform-to-outline      :visible (org-at-item-p)])))			      ;     ["Jump" org-goto])))(defun org-mouse-get-context (contextlist context)  (let ((contextdata (find-if (lambda (x) (eq (car x) context)) contextlist)))    (when contextdata      (save-excursion 	(goto-char (nth 1 contextdata));	(looking-at regexp)))))	(re-search-forward ".*" (nth 2 contextdata))))))(defun org-mouse-for-each-item (function)  (save-excursion     (ignore-errors       (while t (org-previous-item)))    (ignore-errors       (while t 	(funcall function)	(org-next-item)))))(defun org-mouse-bolp ()  "Returns true if there only spaces, tabs, and '*',  between the beginning of line and the point"  (save-excursion    (skip-chars-backward " \t*") (bolp)))  (defun org-mouse-insert-item (text)  (case (org-mouse-line-position)    (:begin			; insert before      (beginning-of-line)      (looking-at "[ \t]*")     (open-line 1)     (indent-to (- (match-end 0) (match-beginning 0)))     (insert "+ "))	     (:middle			; insert after     (end-of-line)      (newline t)      (indent-relative)     (insert "+ "))    (:end				; insert text here     (skip-chars-backward " \t")      (kill-region (point) (point-at-eol))     (unless (looking-back org-mouse-punctuation)        (insert (concat org-mouse-punctuation " ")))))      (insert text)  (beginning-of-line))(defadvice dnd-insert-text (around org-mouse-dnd-insert-text activate)  (if (eq major-mode 'org-mode)      (org-mouse-insert-item text)    ad-do-it))(defadvice dnd-open-file (around org-mouse-dnd-open-file activate)  (if (eq major-mode 'org-mode)      (org-mouse-insert-item uri)    ad-do-it))(defun org-mouse-match-closure (function)  (let ((match (match-data t)))    `(lambda (&rest rest)       (save-match-data	(set-match-data ',match)	(apply ',function rest)))))(defun org-mouse-match-todo-keyword ()  (save-excursion    (org-back-to-heading)    (if (looking-at outline-regexp) (goto-char (match-end 0)))    (or (looking-at (concat " +" org-todo-regexp " *"))	(looking-at " \\( *\\)"))))(defun org-mouse-yank-link (click)  (interactive "e")  ;; Give temporary modes such as isearch a chance to turn off.  (run-hooks 'mouse-leave-buffer-hook)  (mouse-set-point click)  (setq mouse-selection-click-count 0)  (delete-horizontal-space)  (insert-for-yank (concat " [[" (current-kill 0) "]] ")))(defun org-mouse-context-menu (&optional event)  (let ((stamp-prefixes (list org-deadline-string org-scheduled-string))	(contextlist (org-context)))    (flet ((get-context (context) (org-mouse-get-context contextlist context)))  (cond   ((org-mouse-mark-active)    (let ((region-string (buffer-substring (region-beginning) (region-end))))      (popup-menu       `(nil	 ["Sparse Tree" (org-occur ',region-string)]	 ["Find in Buffer" (occur ',region-string)]	 ["Grep in Current Dir" 	  (grep (format "grep -rnH -e '%s' *" ',region-string))]	 ["Grep in Parent Dir" 	  (grep (format "grep -rnH -e '%s' ../*" ',region-string))]	 "--"	 ["Convert to Link" 	  (progn (save-excursion (goto-char (region-beginning)) (insert "[["))		 (save-excursion (goto-char (region-end)) (insert "]]")))]	 ["Insert Link Here" (org-mouse-yank-link ',event)]))))   ((save-excursion (beginning-of-line) (looking-at "#\\+STARTUP: \\(.*\\)"))    (popup-menu      `(nil        ,@(org-mouse-list-options-menu (mapcar 'car org-startup-options)				      'org-mode-restart))))   ((or (eolp) 	(and (looking-at "  \\|\t") (looking-back "  \\|\t")))    (org-mouse-popup-global-menu))   ((get-context :checkbox)    (popup-menu      '(nil        ["Toggle" org-toggle-checkbox t]       ["Remove" org-mouse-remove-match-and-spaces t]       ""       ["All Clear" (org-mouse-for-each-item		     (lambda ()		       (when (save-excursion (org-at-item-checkbox-p))			 (replace-match "[ ]"))))]       ["All Set" (org-mouse-for-each-item		     (lambda ()		       (when (save-excursion (org-at-item-checkbox-p))			 (replace-match "[X]"))))]       ["All Toggle" (org-mouse-for-each-item 'org-toggle-checkbox) t]       ["All Remove" (org-mouse-for-each-item		     (lambda ()		       (when (save-excursion (org-at-item-checkbox-p))			 (org-mouse-remove-match-and-spaces))))]       )))   ((and (org-mouse-looking-at "\\b\\w+" "a-zA-Z0-9_") 	 (member (match-string 0) org-todo-keywords))    (popup-menu      `(nil       ,@(org-mouse-keyword-replace-menu org-todo-keywords)       "--"        ["Check TODOs" org-show-todo-tree t]       ["List all TODO keywords" org-todo-list t]       [,(format "List only %s" (match-string 0)) 	(org-todo-list (match-string 0)) t]       )))   ((and (org-mouse-looking-at "\\b[A-Z]+:" "A-Z")	 (member (match-string 0) stamp-prefixes))    (popup-menu      `(nil        ,@(org-mouse-keyword-replace-menu stamp-prefixes)        "--"       ["Check Deadlines" org-check-deadlines t]       )))   ((org-mouse-looking-at org-mouse-priority-regexp "[]A-Z#") ; priority    (popup-menu `(nil ,@(org-mouse-keyword-replace-menu 			 (org-mouse-priority-list) 1 "Priority %s"))))   ((org-mouse-at-link)    (popup-menu     '(nil       ["Open" org-open-at-point t]       ["Open in Emacs" (org-open-at-point t) t]       "--"       ["Copy link" (kill-new (match-string 0))]       ["Cut link" 	(progn 	  (kill-region (match-beginning 0) (match-end 0))	  (just-one-space))];       ["Paste file link" ((insert "file:") (yank))]       )))   ((org-mouse-looking-at ":\\([A-Za-z0-9_]+\\):" "A-Za-z0-9_" -1) ;tags    (popup-menu      `(nil        [,(format "Display '%s'" (match-string 1))	(org-tags-view nil ,(match-string 1))]       [,(format "Sparse Tree '%s'" (match-string 1))	(org-tags-sparse-tree nil ,(match-string 1))]       "--"       ,@(org-mouse-tag-menu))))   ((org-at-timestamp-p)    (popup-menu      '(nil       ["Show Day" org-open-at-point t]       ["Change Timestamp" org-time-stamp t]       ["Delete Timestamp" (org-mouse-delete-timestamp) t]       ["Compute Time Range" org-evaluate-time-range (org-at-date-range-p)]       "--"       ["Set for Today" org-mouse-timestamp-today]       ["Set for Tomorrow" (org-mouse-timestamp-today 1 'day)]       ["Set in 1 Week" (org-mouse-timestamp-today 7 'day)]       ["Set in 2 Weeks" (org-mouse-timestamp-today 14 'day)]       ["Set in a Month" (org-mouse-timestamp-today 1 'month)]       "--"       ["+ 1 Day" (org-timestamp-change 1 'day)]       ["+ 1 Week" (org-timestamp-change 7 'day)]       ["+ 1 Month" (org-timestamp-change 1 'month)]       "--"       ["- 1 Day" (org-timestamp-change -1 'day)]       ["- 1 Week" (org-timestamp-change -7 'day)]       ["- 1 Month" (org-timestamp-change -1 'month)])))   ((and (assq :headline contextlist) (not (eolp)))    (let ((priority (org-mouse-get-priority t)))      (popup-menu       `("Headline Menu"	 ("Tags and Priorities" 	  ,@(org-mouse-keyword-menu 	     (org-mouse-priority-list) 	     '(lambda (keyword) 		(org-mouse-set-priority (string-to-char keyword)))	     priority "Priority %s")	  "--"	  ,@(org-mouse-tag-menu))	 ("TODO Status"	  ,@(progn (org-mouse-match-todo-keyword)		   (org-mouse-keyword-replace-menu org-todo-keywords 1)))	 ["Show Tags" 	  (with-current-buffer org-mouse-main-buffer (org-agenda-show-tags))	  :visible (not org-mouse-direct)]	 ["Show Priority" 	  (with-current-buffer org-mouse-main-buffer (org-agenda-show-priority))	  :visible (not org-mouse-direct)]	 ,@(if org-mouse-direct '("--") nil)	 ["New Heading" org-mouse-insert-heading :visible org-mouse-direct]	 ["Set Deadline" 	  (progn (org-mouse-end-headline) (insert " ") (org-deadline)) 	  :active (not (save-excursion 			 (org-mouse-re-search-line org-deadline-regexp)))]	 ["Schedule Task" 	  (progn (org-mouse-end-headline) (insert " ") (org-schedule)) 	  :active (not (save-excursion 			 (org-mouse-re-search-line org-scheduled-regexp)))]	 ["Insert Timestamp" 	  (progn (org-mouse-end-headline) (insert " ") (org-time-stamp nil)) t];	 ["Timestamp (inactive)" org-time-stamp-inactive t]	 "--"	 ["Archive Subtree" org-archive-subtree]	 ["Cut Subtree"  org-cut-special]	 ["Copy Subtree"  org-copy-special]	 ["Paste Subtree"  org-paste-special :visible org-mouse-direct]	 "--"	 ["Move Trees" org-mouse-move-tree :active nil]	 ))))   (t     (org-mouse-popup-global-menu))))))   ;; (defun org-mouse-at-regexp (regexp);;   (save-excursion;;     (let ((point (point));; 	  (bol (progn (beginning-of-line) (point)));; 	  (eol (progn (end-of-line) (point))));;       (goto-char point);;       (re-search-backward regexp bol 1);;       (and (not (eolp));; 	   (progn (forward-char);; 		  (re-search-forward regexp eol t));; 	   (<= (match-beginning 0) point)))))(defun org-mouse-mark-active ()  (and mark-active transient-mark-mode))(defun org-mouse-in-region-p (pos)  (and (org-mouse-mark-active)        (>= pos (region-beginning))        (<  pos (region-end))))(defun org-mouse-down-mouse (event)  (interactive "e")  (setq this-command last-command)  (unless (and (= 1 (event-click-count event))	       (org-mouse-in-region-p (posn-point (event-start event))))    (mouse-drag-region event)))(add-hook 'org-mode-hook  '(lambda ()     (setq org-mouse-context-menu-function 'org-mouse-context-menu);     (define-key org-mouse-map [follow-link] 'mouse-face)     (define-key org-mouse-map (if (featurep 'xemacs) [button3] [mouse-3]) nil)     (define-key org-mode-map [mouse-3] 'org-mouse-show-context-menu)     (define-key org-mode-map [down-mouse-1] 'org-mouse-down-mouse)     (define-key org-mouse-map [C-drag-mouse-1] 'org-mouse-move-tree)     (define-key org-mouse-map [C-down-mouse-1] 'org-mouse-move-tree-start)     (define-key org-mode-map [S-mouse-2] 'org-mouse-yank-link)     (define-key org-mode-map [drag-mouse-3] 'org-mouse-yank-link)     (define-key org-mouse-map [drag-mouse-3] 'org-mouse-move-tree)     (define-key org-mouse-map [down-mouse-3] 'org-mouse-move-tree-start)     (font-lock-add-keywords nil 	`((,outline-regexp 	   0 `(face org-link mouse-face highlight keymap ,org-mouse-map)  	   'prepend)	  ("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +" 	   (1 `(face org-link keymap ,org-mouse-map mouse-face highlight) 'prepend))	  ("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)" 	   (2 `(face bold keymap ,org-mouse-map mouse-face highlight) t))) 	t)     (defadvice org-open-at-point (around org-mouse-open-at-point activate)       (let ((context (org-context)))	 (cond 	  ((assq :headline-stars context) (org-cycle))	  ((assq :checkbox context) (org-toggle-checkbox))	  ((assq :item-bullet context)	   (let ((org-cycle-include-plain-lists t)) (org-cycle)))	  (t ad-do-it))))))(defun org-mouse-move-tree-start (event)  (interactive "e")  (message "Same line: promote/demote, (***):move before, (text): make a child"))(defun org-mouse-make-marker (position)  (with-current-buffer (window-buffer (posn-window position))    (copy-marker (posn-point position))))(defun org-mouse-move-tree (event)  ;; todo: handle movements between different buffers  (interactive "e")  (save-excursion    (let* ((start (org-mouse-make-marker (event-start event)))	   (end (org-mouse-make-marker (event-end event)))	   (sbuf (marker-buffer start))	   (ebuf (marker-buffer end)))     (when (and sbuf ebuf)      (set-buffer sbuf)      (goto-char start)      (org-back-to-heading)      (if (and (eq sbuf ebuf)	       (equal 		(point)		(save-excursion (goto-char end) (org-back-to-heading) (point))))	;; if the same line then promote/demote	(if (>= end start) (org-demote-subtree) (org-promote-subtree))      ;; if different lines then move      (org-cut-subtree)            (set-buffer ebuf)      (goto-char end)      (org-back-to-heading)      (when  (and (eq sbuf ebuf)		  (equal 		   (point)		   (save-excursion (goto-char start) 				   (org-back-to-heading) (point))))	(outline-end-of-subtree)	(end-of-line)	(if (eobp) (newline) (forward-char)))            (when (looking-at outline-regexp)	(let ((level (- (match-end 0) (match-beginning 0))))	  (when (> end (match-end 0))	    (outline-end-of-subtree)	    (end-of-line)	    (if (eobp) (newline) (forward-char))	    (setq level (1+ level)))	  (org-paste-subtree level)	  (save-excursion	    (outline-end-of-subtree)	    (when (bolp) (delete-char -1))))))))))(defun org-mouse-transform-to-outline ()  (interactive)  (org-back-to-heading)  (let ((minlevel 1000)	(replace-text (concat (match-string 0) "* ")))    (beginning-of-line 2)    (save-excursion      (while (not (or (eobp) (looking-at outline-regexp)))	(when (looking-at org-mouse-plain-list-regexp)	  (setq minlevel (min minlevel (- (match-end 1) (match-beginning 1)))))	(forward-line)))    (while (not (or (eobp) (looking-at outline-regexp)))      (when (and (looking-at org-mouse-plain-list-regexp)		 (eq minlevel (- (match-end 1) (match-beginning 1))))	(replace-match replace-text))      (forward-line))))	          (defun org-mouse-do-remotely (command);  (org-agenda-check-no-diary)  (when (get-text-property (point) 'org-marker)    (let* ((anticol (- (point-at-eol) (point)))	   (marker (get-text-property (point) 'org-marker))	   (buffer (marker-buffer marker))	   (pos (marker-position marker))	   (hdmarker (get-text-property (point) 'org-hd-marker))	   (buffer-read-only nil)	   (newhead "--- removed ---")	   (org-mouse-direct nil)	   (org-mouse-main-buffer (current-buffer)))      (when (eq (with-current-buffer buffer major-mode) 'org-mode)	(let ((endmarker (save-excursion 			  (set-buffer buffer) 			  (outline-end-of-subtree) 			  (forward-char 1)			  (copy-marker (point)))))	  (with-current-buffer buffer	    (widen)	    (goto-char pos)	    (org-show-hidden-entry)	    (save-excursion	      (and (outline-next-heading)		   (org-flag-heading nil)))   ; show the next heading	    (org-back-to-heading)	    (setq marker (copy-marker (point)))	    (goto-char (max (point-at-bol) (- (point-at-eol) anticol)))	    (funcall command)	    (unless (eq (marker-position marker) (marker-position endmarker))	      (setq newhead (org-get-heading))))	  	  (beginning-of-line 1)	  (save-excursion	    (org-agenda-change-all-lines newhead hdmarker 'fixface)))	t))))(defun org-mouse-agenda-context-menu (&optional event)  (or (org-mouse-do-remotely 'org-mouse-context-menu)      (popup-menu         '("Agenda"	 ("Agenda Files")	 "--"	 ["Rebuild Buffer" org-agenda-redo t]	 ["New Diary Entry" 	  org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline) t]	 "--"	 ["Goto Today" org-agenda-goto-today 	  (org-agenda-check-type nil 'agenda 'timeline) t]	 ["Display Calendar" org-agenda-goto-calendar 	  (org-agenda-check-type nil 'agenda 'timeline) t]	 ("Calendar Commands"	  ["Phases of the Moon" org-agenda-phases-of-moon 	   (org-agenda-check-type nil 'agenda 'timeline)]	  ["Sunrise/Sunset" org-agenda-sunrise-sunset 	   (org-agenda-check-type nil 'agenda 'timeline)]	  ["Holidays" org-agenda-holidays 	   (org-agenda-check-type nil 'agenda 'timeline)]	  ["Convert" org-agenda-convert-date 	   (org-agenda-check-type nil 'agenda 'timeline)]	  "--"	  ["Create iCalendar file" org-export-icalendar-combine-agenda-files t])	 "--"	 ["Day View" org-agenda-day-view 	  :active (org-agenda-check-type nil 'agenda)	  :style radio :selected (equal org-agenda-ndays 1)]	 ["Week View" org-agenda-week-view 	  :active (org-agenda-check-type nil 'agenda)	  :style radio :selected (equal org-agenda-ndays 7)]	 "--"	 ["Show Logbook entries" org-agenda-log-mode	  :style toggle :selected org-agenda-show-log 	  :active (org-agenda-check-type nil 'agenda 'timeline)]	 ["Include Diary" org-agenda-toggle-diary	  :style toggle :selected org-agenda-include-diary 	  :active (org-agenda-check-type nil 'agenda)]	 ["Use Time Grid" org-agenda-toggle-time-grid	  :style toggle :selected org-agenda-use-time-grid	  :active (org-agenda-check-type nil 'agenda)]	 ["Follow Mode" org-agenda-follow-mode	  :style toggle :selected org-agenda-follow-mode]	 "--"	 ["Quit" org-agenda-quit t]	 ["Exit and Release Buffers" org-agenda-exit t]	 ))))(defun org-mouse-get-gesture (event)  (let ((startxy (posn-x-y (event-start event)))	(endxy (posn-x-y (event-end event))))    (if (< (car startxy) (car endxy)) :right :left))); (setq org-agenda-mode-hook nil)(add-hook 'org-agenda-mode-hook    '(lambda ()     (setq org-mouse-context-menu-function 'org-mouse-agenda-context-menu)     (define-key org-agenda-keymap        (if (featurep 'xemacs) [button3] [mouse-3])        'org-mouse-show-context-menu)     (define-key org-agenda-keymap [down-mouse-3] 'org-mouse-move-tree-start)     (define-key org-agenda-keymap [C-mouse-4] 'org-agenda-earlier)     (define-key org-agenda-keymap [C-mouse-5] 'org-agenda-later)     (define-key org-agenda-keymap [drag-mouse-3]       '(lambda (event) (interactive "e")	  (case (org-mouse-get-gesture event)	    (:left (org-agenda-earlier 1))	    (:right (org-agenda-later 1)))))))(provide 'org-mouse)  
 |