;-*- coding: utf-8 -*- ; Xah Lee's emacs customization related to google earth, and also a Geogebra function that work similarly. ; 2007-10, 2011-10-21 ; Xah Lee ; ∑ http://xahlee.org/ ;; § ---------------------------------------- (defun grab-lines (n) "Delete the next n lines and return a list where each element is a line." (interactive) (move-beginning-of-line 1) (let (t1 t2 cl (lines '())) (dotimes (x n) (progn (setq t1 (point)) (move-end-of-line nil) (setq t2 (point)) (setq cl (buffer-substring-no-properties t1 t2)) (delete-region t1 t2) (delete-char 1) (push cl lines) ) ) (setq lines (reverse lines)) ; (prin1 lines (current-buffer)) )) (defun insert-google-map-link (&optional title longitude-latitude) "Insert HTML link to Google Map. Takes 2 optional parameters: title and [longitude latitude] The longitude must be a decimal number. Positive signifies east, negative signifies west. Similar for latitude. Example of inserted text: " (interactive) (let ( ξtitle coordy coordx) (setq ξtitle (if title title "")) (if longitude-latitude (progn (setq coordx (elt longitude-latitude 0)) (setq coordy (elt longitude-latitude 1)) ) (progn (setq coordx "coordx") (setq coordy "coordy") ) ) (insert "\n"))) (defun insert-google-earth-link (&optional title filePath) "Insert a HTML markup for link to a local Goole Earth file. TITLE is the title attribute in the anchor link. FILE-PATH is the path to the KML file. Here's a sample inserted text: " (interactive) (when (not title) (setq title "�") ) (when (not filePath) (setq filePath "�") ) (insert "\n") ) (defun insert-kml (&optional title longitude-latitude sourceFilePath) "Insert a simple Google Earth KML markup template. TITLE is the name to use for the tag. longitude-latitude is a vector [longitude latitude]. They must be real numbers. SOURCEFILEPATH is the file that links to this kml file, used in the tag." (interactive) (let (coord-x coord-y) (when (not title) (setq title "�")) (if longitude-latitude (progn (setq coord-x (elt longitude-latitude 0)) (setq coord-y (elt longitude-latitude 1)) ) (progn (setq coord-x 0) (setq coord-y 0) ) ) (insert " " title " See: http://xahlee.org/" (when sourceFilePath (file-relative-name sourceFilePath "~/web/xahlee_org/" )) " " (number-to-string coord-x) "," (number-to-string coord-y) " \n"))) (defun latitude-longitude-decimalize (latlon) "Convert latitude longitude string LATLON in minutes second format to decimal. For example: 「37°26′36.42″N 06°15′14.28″W」 becomes " (interactive) (let (ξtmpPair (tt2 latlon) ξlatStr ξlatNum ξlonStr ξlonNum ξdeg ξmin ξsec ξsign (ξc (/ 1.0 60.0)) ) (setq tt2 (replace-regexp-in-string "''" "″" tt2 t t) ) (setq tt2 (replace-regexp-in-string "\"" "″" tt2 t t) ) (setq tt2 (replace-regexp-in-string "'" "′" tt2 t t) ) (setq ξtmpPair (split-string tt2 " +")) (when (not (equal (length ξtmpPair) 2)) (error "Error. Input can contain only one space.")) (setq ξlatStr (elt ξtmpPair 0)) (setq ξlonStr (elt ξtmpPair 1)) (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" ξlatStr ) (progn (setq ξdeg (string-to-number (match-string 1 ξlatStr) )) (setq ξmin (string-to-number (match-string 2 ξlatStr) )) (setq ξsec (string-to-number (match-string 3 ξlatStr) )) (setq ξsign (match-string 4 ξlatStr)) (setq ξlatNum (+ ξdeg (* (+ ξmin (* ξsec ξc)) ξc))) (cond ((string= (downcase ξsign) "n") nil) ((string= ξsign "") nil) ((string= (downcase ξsign) "s") (setq ξlatNum (* -1 ξlatNum) )) (t (error "your input is malformed. Your latitude ends with a char that's not “N” or “S”.")) ) ) (progn (error "your latitude is malformed.") ) ) (if (string-match "\\`\\([0-9]+\\)°\\([0-9]+\\)′\\([.0-9]+\\)″\\(.?\\)\\'" ξlonStr ) (progn (setq ξdeg (string-to-number (match-string 1 ξlonStr) )) (setq ξmin (string-to-number (match-string 2 ξlonStr) )) (setq ξsec (string-to-number (match-string 3 ξlonStr) )) (setq ξsign (match-string 4 ξlonStr)) (setq ξlonNum (+ ξdeg (* (+ ξmin (* ξsec ξc)) ξc))) (cond ((string= (downcase ξsign) "e") nil) ((string= ξsign "") nil) ((string= (downcase ξsign) "w") (setq ξlonNum (* -1 ξlonNum) )) (t (error "your input is malformed. Your longitude ends with a char that's not “E” or “W”.")) ) ) (progn (error "your longitude is malformed.") ) ) (vector ξlatNum ξlonNum) ) ) (latitude-longitude-decimalize "37°26′36.42″N 06°15′14.28″W") ;; (defun minsec-to-dec (latlong) ;; "Convert latitude longitude string LATLONG in minutes second format to decimal. ;; For example: 「37°26′36.42″N 06°15′14.28″W」 ;; becomes ;; " ;; (interactive) ;; (let (var1) ;; (setq var1 some) ;; )) (defun make-google-earth () "Create a KML file and replace the current line as a link to it. The current line must have data of this format: ‹title›|‹longitude›|‹latitude› Example: Las Vegas|-115.1730|36.1027 The line will be replaced to like this: The KML file will be created at: 〔~/web/xahlee_org/kml/‹title›.kml〕." (interactive) (let ( myTitle coord-x coord-y inputStr titleCoordList kmlFilePath kmlDirRoot sourceFilePath doit-p p1 p2 ) (setq p1 (line-beginning-position)) (setq p2 (line-end-position)) (setq inputStr (buffer-substring-no-properties p1 p2 )) (setq kmlDirRoot "~/web/xahlee_org/kml/") (setq titleCoordList (split-string inputStr "|")) (setq myTitle (elt titleCoordList 0)) (setq coord-x (trim-string (replace-regexp-in-string "°" "" (elt titleCoordList 1)))) (setq coord-y (trim-string (replace-regexp-in-string "°" "" (elt titleCoordList 2)))) (setq sourceFilePath buffer-file-name) (setq kmlFilePath (concat (file-relative-name kmlDirRoot ) (asciify-text (replace-pairs-in-string (trim-string (elt (split-string myTitle ",") 0)) [[" " "_"] ["," "_"]])) ;; (replace-regexp-in-string " " "_" title) ".kml")) (setq doit-p t) (when (file-exists-p kmlFilePath) (setq doit-p nil) (setq doit-p (y-or-n-p (format "File exist at %s\nDo you want to replace it?" kmlFilePath))) ) (when doit-p (delete-region p1 p2) (insert-google-map-link myTitle (vector (string-to-number coord-x) (string-to-number coord-y))) (insert-google-earth-link myTitle kmlFilePath) (find-file kmlFilePath) (erase-buffer) (insert-kml myTitle (vector (string-to-number coord-x) (string-to-number coord-y)) sourceFilePath) (search-backward "") (forward-char 14) (nxml-mode) (save-buffer) ) )) ;; § ---------------------------------------- (defun insert-ggb-link (fileCoreName fileTitle) "Insert HTML link to GeoGebra (“.ggb”) file." (interactive) (insert "" fileTitle "")) (defun make-ggb () "Create a Geogebra file set and link. This function will take 2 lines the cursor is on as input, create a Geogebra file (.ggb), create a HTML file that embed the ggb applet, and insert a link to the html file in the current buffer. The cursor must be on 2 lines separated by empty lines. The lines are: fileCoreName fileTitle For Example: ellipse_trace Ellisp Tracing make-ggb will then create the files at: ~/web/SpecialPlaneCurves_dir/ggb/ellipse_trace.html ~/web/SpecialPlaneCurves_dir/ggb/ellipse_trace.ggb and the html file's tag content will be “Ellisp Tracing”. The ggb file is copied from a template file at ~/web/SpecialPlaneCurves_dir/ggb/x-template.ggb The html file is copied from a template file at ~/web/SpecialPlaneCurves_dir/ggb/x-template.html Finally, the 2 input lines will be replaced by this link: <p><img src=\"../../ics/ggb.gif\" alt=\"ggb icon\"> <a href=\"../ggb/ellipse_trace.html\">Ellisp Tracing</a></p>" (interactive) (let (fileCoreName fileTitle sl vl ggbFileName htmlFileName dirPath linkBackRelativePath linkBackTitle) (search-backward "\n\n") (search-forward "\n\n") (setq sl '(fileCoreName fileTitle)) ;; sl = symbol list; vl = value list (setq vl (grab-lines 2)) (while sl (set (pop sl) (pop vl))) ;; returns this "../Ellipse_dir/ellipse.html" (setq linkBackRelativePath (concat ".." (substring (buffer-file-name) 37))) (setq linkBackTitle (get-html-file-title (buffer-file-name))) (setq dirPath "~/web/SpecialPlaneCurves_dir/ggb/") (setq ggbFileName (concat dirPath fileCoreName ".ggb")) (setq htmlFileName (concat dirPath fileCoreName ".html")) (insert-ggb-link fileCoreName fileTitle) (insert "\n") (copy-file (concat dirPath "x-template.ggb") ggbFileName) (copy-file (concat dirPath "x-template.html") htmlFileName) (let (mybuff (case-replace nil) (case-fold-search nil)) (setq mybuff (find-file htmlFileName)) (goto-char (point-min)) (while (search-forward "「fileTitle」" nil t) (replace-match fileTitle nil t)) (goto-char (point-min)) (while (search-forward "「fileCoreName」" nil t) (replace-match fileCoreName nil t)) (goto-char (point-min)) (while (search-forward "「linkBackRelativePath」" nil t) (replace-match linkBackRelativePath nil t)) (goto-char (point-min)) (while (search-forward "「linkBackTitle」" nil t) (replace-match linkBackTitle nil t)) (save-buffer) (kill-buffer mybuff) ) (shell-command (concat "open " ggbFileName)) ))