1 ;;; html-move.el --- Move a file in a local file web site.
3 ;; Author: Lennart Borgman (lennart O borgman A gmail O com)
4 ;; Created: Thu Jan 12 08:11:30 2006
5 (defconst html-move:version "0.31") ;; Version:
6 ;; Last-Updated: Tue Feb 20 23:59:43 2007 (3600 +0100)
10 ;; Features that might be required by this library:
14 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 ;; Functions for moving a file in a local file web site. Moves the
21 ;; file and fixes the local affected links after the move.
23 ;; To use this file you may in your .emacs put
25 ;; (require 'html-move)
27 ;; Call the function `html-move-buffer-file' to move a file.
29 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36 ;; This program is free software; you can redistribute it and/or modify
37 ;; it under the terms of the GNU General Public License as published by
38 ;; the Free Software Foundation; either version 2, or (at your option)
41 ;; This program is distributed in the hope that it will be useful,
42 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
43 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 ;; GNU General Public License for more details.
46 ;; You should have received a copy of the GNU General Public License
47 ;; along with this program; see the file COPYING. If not, write to the
48 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
49 ;; Boston, MA 02111-1307, USA.
51 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55 (eval-when-compile (add-to-list 'load-path default-directory load-path))
56 (eval-when-compile (require 'html-site nil t))
59 (defun html-move-make-new-url (old-url from-dir to-dir)
60 "Make new relative url.
61 If OLD-URL is an absolute path then return it. Otherwise OLD-URL
62 is assumed to be relative FROM-DIR. Return a new url relative
63 TO-DIR that gives the same absolute path."
64 (if (or (file-name-absolute-p old-url)
65 (char-equal ?# (string-to-char old-url))
66 (let ((urlobj (url-generic-parse-url old-url)))
71 (relative-path (file-relative-name from-dir to-dir))
72 (new-abs-url (expand-file-name (concat relative-path old-url) to-dir))
73 (new-url (file-relative-name new-abs-url to-dir)))
77 (defun html-move-in-dir-tree (file tree)
78 (let ((rel-path (file-relative-name file tree)))
79 (or (string= "." rel-path)
80 (not (string= ".." (substring rel-path 0 2))))))
82 (defun html-move-buffer-file (to)
83 "Move current buffer file to another directory and/or name.
84 Correct the affected relative links in the moved file and the
85 links to the file moved in the directory tree
86 `html-site-current-site-dir'."
87 ;;(interactive "GMove to: ")
89 (let* ((use-dialog-box nil)
90 (name (read-file-name "Move to (directory or file name): "
93 (list (expand-file-name name))))
94 (html-site-current-ensure-site-defined)
95 (let ((from (buffer-file-name))
96 (site-directory (html-site-current-site-dir)))
98 (error "No buffer file name, can't move file!"))
99 (let* ((from-dir (file-name-directory from))
100 (from-ext (file-name-extension from))
107 (unless (html-move-in-dir-tree from-dir site-directory)
108 (error "Buffer file is not in site directory tree"))
109 (if (file-directory-p to)
112 (setq new-name (file-name-nondirectory from))
114 (setq to-ext (file-name-extension to))
115 (unless (string= to-ext from-ext)
117 (error "Can't find directory %s (or missing extension?)" to)
118 (error "Move must not change file extension")))
119 (setq to-dir (file-name-directory to))
120 (unless (file-directory-p to-dir)
121 (if (file-exists-p to-dir)
122 (error "Not a directory: %s" to-dir)
123 (error "Can't find directory %s" to-dir)))
124 (setq new-name (file-name-nondirectory to))
127 (unless (html-move-in-dir-tree to-dir site-directory)
128 (error "Target is not in site directory tree"))
131 (setq relative-path (file-relative-name to-dir from-dir))
132 (when (file-name-absolute-p relative-path)
133 (error "Can't make a relative path from %s to %s" from to))
134 (setq new-file (expand-file-name new-name to))
135 (let ((moved-buffer (current-buffer))
136 (moved-contents (buffer-substring-no-properties
139 (when (file-exists-p new-file)
140 (error "File already exists: %s" new-file))
141 ;; Open in new location
143 (setq new-buffer (current-buffer))
145 (insert moved-contents)
146 (goto-char (point-min))
147 (while (re-search-forward "\\(?:href\\|src\\)\\s-*=\\s-*\"\\([^\"]*\\)\"" nil t)
148 (let ((old-url (match-string 1))
150 (unless (or (> 11 (length old-url))
151 (string= "javascript:"
152 (downcase (substring old-url 0 11))))
153 (setq new-url (html-move-make-new-url old-url from-dir to-dir))
155 (replace-match new-url t t nil 1)))))
157 (html-move-fix-site-backlinks from to-dir from-dir)
158 ;; Make backup at current location of "from" file
159 (with-current-buffer moved-buffer
160 (set-buffer-modified-p t)
162 (kill-buffer moved-buffer)
165 (set-buffer new-buffer)
166 (goto-char (point-min))
167 (lwarn '(html-move) :warning "Moved to %s" new-file)
170 (defun html-move-fix-site-backlinks (to-moved-file to-dir from-dir)
171 "Fix all links back to TO-MOVED-FILE.
172 This is called by `html-move-buffer-file' to fix all links back
173 to the moved file. TO-MOVED-FILE is the old location of the
174 moved file. FROM-DIR is the old directory and TO-DIR the target
175 directory for the move."
176 (html-move-fix-all-backlinks to-moved-file (html-site-current-site-dir) to-dir from-dir)
177 (when (html-move-fix-page-list to-moved-file to-dir from-dir)
178 (message "Page list for site TOC changed. You need to update TOC.")
179 (lwarn '(html-move-fix-site-backlinks) :warning "Page list for site TOC changed. You need to update TOC.")
182 (defun html-move-fix-all-backlinks (to-moved-file for-dir to-dir from-dir)
183 ;;(message "for-dir=%s" for-dir);(sit-for 2)
184 (let ((html-files (directory-files for-dir t ".*\\.html?$"))
185 (sub-dirs (directory-files-and-attributes for-dir t)))
186 (dolist (html-file html-files)
187 (html-move-fix-backlinks to-moved-file html-file to-dir from-dir))
188 (dolist (sub-entry sub-dirs)
189 (let* ((sub-dir (car sub-entry))
190 (sub-name (file-name-nondirectory sub-dir)))
191 (when (and (eq t (car (cdr sub-entry)))
192 (not (string= "." sub-name))
193 (not (string= ".." sub-name)))
194 (html-move-fix-all-backlinks to-moved-file sub-dir to-dir from-dir))))))
196 (defun html-move-fix-backlinks (to-moved-file for-file to-dir from-dir)
197 (when (file-exists-p for-file)
198 (let ((old-file-buffer (get-file-buffer for-file))
199 (buffer (find-file-noselect for-file)))
200 (with-current-buffer buffer
201 (goto-char (point-min))
204 "\\(?:href\\|src\\)\\s-*=\\s-*\"\\([^#\"]*\\)\\(?:#[^\"]*\\|\\)\""
206 (let* ((old-url (match-string 1))
207 (old-absolute-url (expand-file-name
209 (file-name-directory for-file)))
211 (when (string= old-absolute-url to-moved-file)
212 (setq new-url (html-move-make-new-url old-url to-dir from-dir))
213 ;;(message "new-backlink=%s" new-url);(sit-for 2)
214 (replace-match new-url t t nil 1)
217 (unless old-file-buffer
218 (kill-this-buffer))))))
220 (defun html-move-fix-page-list (to-moved-file to-dir from-dir)
221 (let ((for-file (html-site-current-page-list))
223 (when (file-exists-p for-file)
224 (let ((old-file-buffer (get-file-buffer for-file))
225 (buffer (find-file-noselect for-file)))
226 (with-current-buffer buffer
227 (goto-char (point-min))
230 ;;"\\(?:href\\|src\\)\\s-*=\\s-*\"\\([^#\"]*\\)\\(?:#[^\"]*\\|\\)\""
231 "\\s-+###\\s-+\\([^#]*?\\)\\(?:#[^#]*\\|\\)[:space:]*$"
233 (let* ((old-url (match-string 1))
234 (old-absolute-url (expand-file-name
236 (file-name-directory for-file)))
238 (when (string= old-absolute-url to-moved-file)
239 (setq new-url (html-move-make-new-url old-url to-dir from-dir))
240 ;;(message "new-backlink=%s" new-url);(sit-for 2)
241 (replace-match new-url t t nil 1)
245 (unless old-file-buffer
246 (kill-this-buffer)))))
250 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
251 ;;; html-move.el ends here