Download
(require 'dnd)
(defvar smart-dnd-protocol-alist
'(("^file:///" . smart-dnd-handle-local-file)
("^file://" . smart-dnd-handle-file)
("^file:" . smart-dnd-handle-local-file))
"The functions to call when a file is dropped to the buffer.
See `dnd-protocol-alist' for more information."
)
(put 'smart-dnd-protocol-alist 'risky-local-variable t)
(defvar smart-dnd-replace-alist
'(
("%F" . f)
("%f" . (file-name-nondirectory f))
("%r" . (if buffer-file-name
(file-relative-name
f (file-name-directory buffer-file-name))
f))
("%R" . (if buffer-file-name
(file-relative-name
f (file-name-directory buffer-file-name))
(concat "file://" f)))
("%n" . (file-name-sans-extension (file-name-nondirectory f)))
("%e" . (or (file-name-extension f) ""))
))
(put 'smart-dnd-replace-alist 'risky-local-variable t)
(defun smart-dnd-handle-local-file (uri action)
"Open a local file. See also `dnd-open-local-file'."
(let* ((f (dnd-get-local-file-name uri t)))
(if (and f (file-readable-p f))
(progn
(or (smart-dnd-execute f)
(dnd-open-local-file uri action))
'private)
(error "Can not read %s" uri))))
(defun smart-dnd-handle-file (uri action)
"Handle a local or remote file."
(let ((local-file (dnd-get-local-file-uri uri)))
(if local-file (smart-dnd-handle-local-file local-file action)
(error "Remote files not supported"))))
(defun smart-dnd-execute (f)
"Execute a Drag'n'Drop action with filename F
depending on `smart-dnd-string-alist'."
(interactive "f")
(save-excursion
(if (eq (car-safe last-nonmenu-event) 'drag-n-drop)
(goto-char (posn-point (car (cdr-safe last-nonmenu-event)))))
(let( (alist smart-dnd-string-alist)
(case-fold-search nil)
(my-string nil)
(succeed nil) )
(while alist
(when (string-match (caar alist) f)
(setq my-string (cdar alist))
(when (stringp my-string)
(insert (smart-dnd-string my-string f))
(setq alist nil)
(setq succeed t)
)
(when (not (stringp my-string))
(eval (cdar alist))
(setq alist nil)
(setq succeed t)
)
)
(setq alist (cdr alist))
)
succeed)))
(defun smart-dnd-setup (alist)
"Install smart-dnd feature to the local buffer."
(interactive)
(set (make-local-variable 'dnd-protocol-alist)
(append smart-dnd-protocol-alist dnd-protocol-alist))
(set (make-local-variable 'smart-dnd-string-alist) alist)
)
(defun smart-dnd-string (string filename)
"Generate a string, based on a format STRING and the FILENAME.
You can use the following keywords in the format control STRING.
%F means absolute pathname. [ /home/zenitani/public_html/index.html ]
%f means file name without directory. [ index.html ]
%r and %R means relative path to the FILENAME from a file in the current buffer.
[ public_html/index.html ]
When the target buffer hasn't been assigned a file name yet,
%r returns the absolute pathname [ /home/zenitani/public_html/index.html ]
while %R returns the URL. [ file:///home/zenitani/ .. /index.html ]
%n means file name without extension. [ index ]
%e means extension of file name. [ html ]
"
(interactive)
(let ((rlist smart-dnd-replace-alist)
(case-fold-search nil)
(f filename))
(while rlist
(while (string-match (caar rlist) string)
(setq string
(replace-match
(eval (cdar rlist)) t nil string)))
(setq rlist (cdr rlist))
))
string)
(provide 'smart-dnd)