;-*- 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:
Ellisp Tracing
"
(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))
))