summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/util/chartg.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/nxhtml/util/chartg.el')
-rw-r--r--emacs.d/nxhtml/util/chartg.el844
1 files changed, 844 insertions, 0 deletions
diff --git a/emacs.d/nxhtml/util/chartg.el b/emacs.d/nxhtml/util/chartg.el
new file mode 100644
index 0000000..7470710
--- /dev/null
+++ b/emacs.d/nxhtml/util/chartg.el
@@ -0,0 +1,844 @@
+;;; chartg.el --- Google charts (and maybe other)
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2008-04-06 Sun
+(defconst chart:version "0.2") ;; Version:
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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, 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; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defconst chartg-types
+ '((line-chartg-x lc)
+ (line-chartg-xy lxy)
+ (line-chart ls)
+
+ (bar-chartg-horizontal bhs)
+ (bar-chartg-vertical bvs)
+ (bar-chartg-horizontal-grouped bhg)
+ (bar-chartg-vertical-grouped bvg)
+
+ (pie-2-dimensional p)
+ (pie-3-dimensional p3)
+
+ (venn-diagram v)
+ (scatter-plot s)
+
+ (radar-chart r)
+ (radar-chartg-w-splines rs)
+
+ (geographical-map t)
+ (meter gom)))
+
+(defconst chartg-types-keywords
+ (mapcar (lambda (rec)
+ (symbol-name (car rec)))
+ chartg-types))
+
+(defvar chartg-mode-keywords-and-states
+ '(("Output-file:" (accept file-name))
+ ("Size:" (accept number))
+ ("Data:" (accept number))
+ ("Type:" (accept chartg-type))
+ ))
+
+(defvar chartg-mode-keywords
+ (mapcar (lambda (rec)
+ (car rec))
+ chartg-mode-keywords-and-states))
+
+;; Fix-me: I started to implement a parser, but I think I will drop it
+;; and wait for Semantic to be easily available instead. Or just use
+;; Calc/Org Tables.
+
+(defvar chartg-intermediate-states
+ '((end-or-label (or end-of-file label))
+ ))
+
+(defvar chartg-extra-keywords-and-states
+ '(
+ ;;("Provider:")
+ ("Colors:")
+ ("Solid-fill:")
+ ("Linear-gradient:")
+ ("Linear-stripes:")
+ ("Chartg-title:" (and string end-or-label))
+ ("Legends:" (accept string))
+ ("Axis-types:")
+ ("Axis-labels:")
+ ("Axis-ranges:")
+ ("Axis-styles:")
+ ("Bar-thickness:")
+ ("Bar-chartg-zero-line:")
+ ("Bar-chartg-zero-line-2:")
+ ("Line-styles-1:")
+ ("Line-styles-2:")
+ ("Grid-lines:")
+ ("Shape-markers:")
+ ("Range-markers:")
+ ))
+
+(defvar chartg-extra-keywords
+ (mapcar (lambda (rec)
+ (car rec))
+ chartg-extra-keywords-and-states))
+
+(defvar chartg-raw-keywords-and-states
+ '(
+ ("Google-chartg-raw:" (accept string))
+ ))
+
+(defvar chartg-raw-keywords
+ (mapcar (lambda (rec)
+ (car rec))
+ chartg-raw-keywords-and-states))
+
+(defvar chartg-mode-keywords-re (regexp-opt chartg-mode-keywords))
+(defvar chartg-extra-keywords-re (regexp-opt chartg-extra-keywords))
+(defvar chartg-types-keywords-re (regexp-opt chartg-types-keywords))
+(defvar chartg-raw-keywords-re (regexp-opt chartg-raw-keywords))
+
+(defvar chartg-font-lock-keywords
+ `((,chartg-mode-keywords-re . font-lock-keyword-face)
+ (,chartg-extra-keywords-re . font-lock-variable-name-face)
+ (,chartg-types-keywords-re . font-lock-function-name-face)
+ (,chartg-raw-keywords-re . font-lock-preprocessor-face)
+ ))
+
+(defvar chartg-font-lock-defaults
+ '(chartg-font-lock-keywords nil t))
+
+(defvar chartg-mode-syntax-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?\n "> " table)
+ (modify-syntax-entry ?\; "< " table)
+ table))
+
+(defun chartg-create (provider out-file size data type
+ title legends &optional extras)
+ "Create a chart image.
+PROVIDER is what to use for creating the chart. Currently only
+`google' for Google's chart API is supported.
+
+OUT-FILE is where the image goes.
+
+SIZE is a cons cell with pixel width and height.
+
+DATA is the data to draw the chart from. It is a list of data
+sets where each data set has the form:
+
+ (list (list NUMBERS ...) (MIN . MAX)))
+
+TYPE can be the following:
+
+* Line charts
+
+ - lc: Line chart with only y values. Each dataset is a new
+ line.
+
+ - lxy: Line chart with both x and y values. For each line there
+ should be a pair of datasets, the first for x and the second
+ for y. If the x dataset just contains a single -1 then values
+ are evenly spaced along the x-axis.
+
+ - ls: Like above, but axis are not drawn.
+
+* Bar charts:
+
+ - bhs: horizontal bars.
+ - bvs: vertical bars.
+ - bhg, bvg: dito grouped.
+
+* Pie charts:
+
+ - cht=p: one dimensional
+ - cht=p3: three dimensional
+
+* Venn diagrams
+
+ - cht=v: data should be specified as
+ * the first three values specify the relative sizes of three
+ circles, A, B, and C
+ * the fourth value specifies the area of A intersecting B
+ * the fifth value specifies the area of A intersecting C
+ * the sixth value specifies the area of B intersecting C
+ * the seventh value specifies the area of A intersecting B
+ intersecting C
+
+* Scatter plots
+
+ - cht=s: Supply a pair of datasets, first for x and second for
+ y coordinates.
+
+* Radar charts
+
+ - cht=r: straight lines.
+ - cht=rs: splines.
+
+ You will have to find out the format of the datasets
+ yourself, I don't understand it ;-)
+
+ Or perhaps mail google?
+
+* Maps
+
+ - cht=t
+
+ together with
+
+ - chtm=AREA: AREA for provider `google' is currently one of
+ * africa
+ * asia
+ * europe
+ * middle_east
+ * south_america
+ * usa
+ * world
+
+* Meter
+
+ - cht=gom: A speed meter type meter. Takes a single value.
+
+TITLE is a string to use as title.
+
+LEGENDS is a list of labels to put on the data.
+
+EXTRAS is a list of extra arguments with the form
+
+ (EXTRA-TYPE EXTRA-VALUE)
+
+Where EXTRA-TYPE is the extra argument type and EXTRA-VALUE the
+value. The following EXTRA-TYPEs are supported:
+
+* COLORS: value is a list of colors corresponding to the list of
+ DATA. Each color have the format RRGGBB or RRGGBBTT where the
+ first form is the normal way to specify colors in rgb-format
+ and the second has an additional TT for transparence. TT=00
+ means completely transparent and TT=FF means completely opaque.
+
+FILL-AREA are fill colors for data sets in line charts. It should
+be a list
+
+ (list COLOR START-INDEX END-INDEX)
+
+"
+ (message "(chartg-create %s %s %s %s %s %s %s" provider out-file size data type
+ title legends)
+ (unless (symbolp type)
+ (error "Argument TYPE should be a symbol"))
+ (unless (assoc type chartg-types)
+ (error "Unknown chart type: %s" type))
+ (cond
+ ((eq provider 'google)
+ (let* ((g-type (nth 1 (assoc type chartg-types)))
+ (width (car size))
+ (height (cdr size))
+ ;;(size-par (format "&chs=%sx%s" width height))
+ ;;
+ numbers
+ scales
+ colors-par
+ ;;
+ url
+ content
+ )
+ (setq url
+ (format
+ "http://chart.apis.google.com/chart?cht=%s&chs=%dx%d" g-type width height))
+ ;;(setq url (concat url size-par))
+ ;; Data and scales
+ (unless data
+ (error "No data"))
+ (dolist (rec data)
+ (let* ((rec-numbers (car rec))
+ (number-str
+ (let (str)
+ (dolist (num rec-numbers)
+ (setq str
+ (if (not str)
+ (number-to-string num)
+ (concat str "," (number-to-string num)))))
+ str))
+ (rec-scale (cadr rec))
+ (rec-min (car rec-scale))
+ (rec-max (cdr rec-scale))
+ (scale-str (when rec-scale (format "%s,%s" rec-min rec-max)))
+ )
+ (if (not numbers)
+ (progn
+ (setq numbers (concat "&chd=t:" number-str))
+ (when (or scale-str
+ (memq g-type '(p p3 gom)))
+ (setq scales (concat "&chds=" scale-str))))
+ (setq numbers (concat numbers "|" number-str))
+ (when scale-str
+ (setq scales (concat scales "," scale-str))))))
+ (setq url (concat url numbers))
+ (when scales (setq url (concat url scales)))
+ ;; fix-me: encode the url
+ (when title (setq url (concat url "&chtt=" (url-hexify-string title))))
+ (when legends
+ (let ((url-legends (mapconcat 'url-hexify-string legends "|"))
+ (arg (if (memq g-type '(p p3 gom))
+ "&chl="
+ "&chdl=")))
+ (setq url (concat url arg url-legends))))
+ (dolist (extra extras)
+ (let ((extra-type (car extra))
+ (extra-value (cdr extra)))
+ (cond
+ ((eq extra-type 'GOOGLE-RAW)
+ (setq url (concat url extra-value)))
+ ((eq extra-type 'colors)
+ ;; Colors
+ (dolist (color extra-value)
+ (if (not colors-par)
+ (setq colors-par (concat "&chco=" color))
+ (setq colors-par (concat colors-par "," color))))
+ (when colors-par (setq url (concat url colors-par))))
+ (t (error "Unsupported extra type: %s" extra-type)))))
+
+ ;;(lwarn t :warning "url=%s" url)(top-level)
+ ;;(setq url (concat url "&chxt=y"))
+ (message "Sending %s" url)
+ (setq content
+ (with-current-buffer (url-retrieve-synchronously url)
+ (goto-char (point-min))
+ (if (search-forward "\n\n" nil t)
+ (buffer-substring-no-properties (point) (point-max))
+ (view-buffer-other-window (current-buffer))
+ (error "Bad content"))))
+ (let* ((is-html (string-match-p "</body></html>" content))
+ (fname (progn
+ (when is-html
+ (setq out-file (concat (file-name-sans-extension out-file) ".html")))
+ (expand-file-name out-file)
+ ))
+ (do-it (or (not (file-exists-p fname))
+ (y-or-n-p
+ (concat "File " fname " exists. Replace it? "))))
+ (buf (find-buffer-visiting fname))
+ (this-window (selected-window)))
+ (when do-it
+ (when buf (kill-buffer buf))
+ (with-temp-file fname
+ (insert content))
+ (if (not is-html)
+ (view-file-other-window fname)
+ (chartg-show-last-error-file fname))
+ (select-window this-window)))))
+ (t (error "Unknown provider: %s" provider)))
+ )
+
+(defun chartg-show-last-error-file (fname)
+ (interactive)
+ (with-output-to-temp-buffer (help-buffer)
+ (help-setup-xref (list #'chartg-show-last-error-file fname) (interactive-p))
+ (with-current-buffer (help-buffer)
+ (insert "Error, see ")
+ (insert-text-button "result error page"
+ 'action
+ `(lambda (btn)
+ (browse-url ,fname))))))
+
+(defvar chartg-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [(meta tab)] 'chartg-complete)
+ (define-key map [(control ?c) (control ?c)] 'chartg-make-chart)
+ map))
+
+(defun chartg-missing-keywords ()
+ (let ((collection (copy-sequence chartg-mode-keywords)))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (while (re-search-forward chartg-mode-keywords-re nil t)
+ (setq collection
+ (delete (match-string-no-properties 0)
+ collection)))))
+ collection))
+
+;;;###autoload
+(defun chartg-complete ()
+ (interactive)
+ (let* ((here (point))
+ (partial (when (looking-back (rx word-start
+ (optional ?\")
+ (0+ (any "[a-z]"))))
+ (match-string-no-properties 0)))
+ (part-pos (if partial
+ (match-beginning 0)
+ (setq partial "")
+ (point)))
+ (state (catch 'pos-state (chartg-get-state (point))))
+ (msg "No completions")
+ collection
+ all
+ prompt
+ res)
+ (when state
+ (cond
+ ((or (= (current-column) 0)
+ (equal state 'need-label))
+ (setq collection (append (chartg-missing-keywords)
+ chartg-extra-keywords
+ chartg-raw-keywords
+ nil))
+ (setq prompt "Label: "))
+ ((equal state '(accept number))
+ (setq res nil)
+ (setq msg (propertize "Needs a number here!"
+ 'face 'secondary-selection)))
+ ((equal state '(accept chartg-type))
+ (setq collection chartg-types-keywords)
+ (setq prompt "Chart type: "))
+ ((equal state '(accept file-name))
+ (setq res
+ (concat "\"" (read-file-name "Output-file: "
+ nil
+ ;; fix-me: handle partial
+ partial)
+ "\""))))
+ (when collection
+ (let ((all (if partial
+ (all-completions partial collection)
+ collection)))
+ (setq res (when all
+ (if (= (length all) 1)
+ (car all)
+ (completing-read prompt collection nil t partial)))))))
+ (if (not res)
+ (message "%s" msg)
+ (insert (substring res (length partial))))))
+
+
+(defun chartg-get-state (want-pos-state)
+ (let* (par-output-file
+ par-provider
+ par-size
+ par-data par-data-temp
+ par-data-min par-data-max
+ par-type
+ par-title
+ par-legends
+ par-google-raw
+ (here (point))
+ token-before-pos
+ pos-state
+ (state 'need-label)
+ (problems
+ (catch 'problems
+ (save-restriction
+ ;;(widen)
+ (if want-pos-state
+ (unless (re-search-backward chartg-mode-keywords-re nil t)
+ (goto-char (point-min)))
+ (goto-char (point-min)))
+ (let (this-keyword
+ this-start
+ this-end
+ params
+ token
+ token-pos
+ next-token
+ found-labels
+ current-label)
+ (while (or token
+ (progn
+ (setq pos-state state)
+ (setq token-before-pos (point))
+ (condition-case err
+ (setq token (read (current-buffer)))
+ (error
+ (if (eq (car err) 'end-of-file)
+ (unless (or (eq state 'need-label)
+ (member '(quote |) state))
+ (throw 'problems (format "Unexpected end, state=%s" state)))
+ (throw 'problems
+ (error-message-string err)))))))
+ (message "token=%s, label=%s, state=%s" token current-label state)
+ (when (and want-pos-state
+ (>= (point) want-pos-state))
+ (when (= (point) want-pos-state)
+ ;; right after item
+ (setq pos-state nil))
+ (goto-char here)
+ (throw 'pos-state pos-state))
+ (when (and (listp state) (memq 'number state))
+ (unless (numberp token)
+ (save-match-data
+ (let ((token-str (format "%s" token)))
+ (setq token-str (replace-regexp-in-string "\\([0-9]\\),\\([0-9]\\)" "\\1\\2" token-str))
+ (when (string-match-p "^[0-9]+$" token-str)
+ (setq token (string-to-number token-str)))))))
+ (cond ;; state
+ ;; Label
+ ((eq state 'need-label)
+ (unless (symbolp token)
+ (throw 'problems (format "Expected label, got %s" token)))
+ (unless (member (symbol-name token)
+ (append chartg-mode-keywords
+ chartg-extra-keywords
+ chartg-raw-keywords
+ nil))
+ (throw 'problems (format "Unknown label %s" token)))
+ (when (member (symbol-name token) found-labels)
+ (throw 'problems (format "Label %s defined twice" token)))
+ (setq current-label token)
+ (setq found-labels (cons current-label found-labels))
+ (setq token nil)
+ ;;(setq state 'need-value)
+ (case current-label
+ ('Output-file:
+ (setq state '(accept file-name)))
+ ('Size:
+ (setq state '(accept number)))
+ ('Data:
+ (setq state '(accept number)))
+ ('Type:
+ (setq state '(accept chartg-type)))
+ ('Chartg-title:
+ (setq state '(accept string)))
+ ('Legends:
+ (setq state '(accept string)))
+ ('Google-chartg-raw:
+ (setq state '(accept string)))
+ ))
+ ;;;; Values
+ ;; Alt
+ ((equal state '(accept '| symbol))
+ (if (eq '| token)
+ (case current-label
+ ('Legends:
+ (setq token nil)
+ (setq state '(accept string)))
+ (t (error "internal error, current-label=%s, state=%s" current-label state)))
+ (if (symbolp token)
+ (progn
+ ;;(setq token nil)
+ (setq state 'need-label))
+ (throw 'problems (format "Expected | or label, got %s" token)))))
+ ;; Strings
+ ((equal state '(accept string))
+ (unless (stringp token)
+ (throw 'problems "Expected string"))
+ (case current-label
+ ('Chartg-title:
+ (setq par-title token)
+ (setq token nil)
+ (setq state 'need-label))
+ ('Legends:
+ (setq par-legends (cons token par-legends))
+ (setq token nil)
+ (setq state '(accept '| symbol)))
+ ('Google-chartg-raw:
+ (setq par-google-raw token)
+ (setq token nil)
+ (setq state 'need-label))
+ (t (error "internal error, current-label=%s, state=%s" current-label state))))
+ ;; Output file
+ ((equal state '(accept file-name))
+ (unless (stringp token)
+ (throw 'problems "Expected file name string"))
+ (assert (eq current-label 'Output-file:))
+ (setq par-output-file token)
+ (setq token nil)
+ (setq state 'need-label))
+ ;; Numbers
+ ((equal state '(accept number))
+ (unless (numberp token)
+ (throw 'problems "Expected number"))
+ (case current-label
+ ('Size:
+ (if (not par-size)
+ (progn
+ (setq par-size token)
+ (setq token nil)
+ (setq state '(accept number 'x 'X)))
+ (setq par-size (cons par-size token))
+ (setq token nil)
+ (setq state 'need-label)))
+ ('Data:
+ ;;(assert (not par-data-temp))
+ (setq par-data-temp (cons token par-data-temp))
+ (setq par-data-min token)
+ (setq par-data-max token)
+ (setq token nil)
+ (setq state '(accept number ', '| symbol))
+ )
+ (t (error "internal error, state=%s, current-label=%s" state current-label)))
+ )
+ ;; Numbers or |
+ ((equal state '(accept number ', '| symbol))
+ (if (numberp token)
+ (progn
+ (setq par-data-min (if par-data-min (min par-data-min token) token))
+ (setq par-data-max (if par-data-max (max par-data-max token) token))
+ (setq par-data-temp (cons token par-data-temp))
+ (message "par-data-min/max=%s/%s, token=%s -- %s" par-data-min par-data-max token par-data-temp)
+ (setq token nil))
+ (if (eq ', token)
+ (setq token nil)
+ (if (or (eq '| token)
+ (symbolp token))
+ (progn
+ (unless par-data-temp
+ (throw 'problems "Empty data set"))
+ (setq par-data (cons (list (reverse par-data-temp) (cons par-data-min par-data-max)) par-data))
+ (setq par-data-temp nil)
+ (setq par-data-min nil)
+ (setq par-data-max nil)
+ (if (not (eq '| token))
+ (setq state 'need-label)
+ (setq state '(accept number))
+ (setq token nil)))
+ (throw 'problems "Expected | or EOF")
+ ))))
+ ;; Numbers or x/X
+ ((equal state '(accept number 'x 'X))
+ (assert (eq current-label 'Size:))
+ (let ((is-n (numberp token))
+ (is-x (memq token '(x X))))
+ (unless (or is-n is-x)
+ (throw 'problems "Expected X or number"))
+ (if is-x
+ (progn
+ (setq token nil)
+ (setq state '(accept number)))
+ (setq par-size (cons par-size token))
+ (setq token nil)
+ (setq state 'need-label))))
+ ;; Chart type
+ ((equal state '(accept chartg-type))
+ (setq par-type token)
+ (unless (assoc par-type chartg-types)
+ (throw 'problems (format "Unknown chart type: %s" par-type)))
+ (setq token nil)
+ (setq state 'need-label))
+ (t (error "internal error, state=%s" state))))))
+ ;; fix-me here
+
+ nil)))
+ (when want-pos-state
+ (goto-char here)
+ (throw 'pos-state state))
+ (unless problems
+ (let ((missing-lab (chartg-missing-keywords)))
+ (when missing-lab
+ (setq problems (format "Missing required labels: %s" missing-lab)))))
+ (if problems
+ (let ((msg (if (listp problems)
+ (nth 1 problems)
+ problems))
+ (where (if (listp problems)
+ (nth 0 problems)
+ token-before-pos)))
+ (goto-char where)
+ (skip-chars-forward " \t")
+ (error msg))
+ (goto-char here)
+ ;;(defun chartg-create (out-file provider size data type &rest extras)
+ (setq par-provider 'google)
+ (setq par-legends (nreverse par-legends))
+ (let ((extras nil))
+ (when par-google-raw
+ (setq extras (cons (cons 'GOOGLE-RAW par-google-raw) extras)))
+ (chartg-create par-provider par-output-file par-size
+ par-data par-type par-title par-legends extras))
+ nil)))
+
+;;;###autoload
+(defun chartg-make-chart ()
+ "Try to make a new chart.
+If region is active then make a new chart from data in the
+selected region.
+
+Else if current buffer is in `chartg-mode' then do it from the
+chart specifications in this buffer. Otherwise create a new
+buffer and initialize it with `chartg-mode'.
+
+If the chart specifications are complete enough to make a chart
+then do it and show the resulting chart image. If not then tell
+user what is missing.
+
+NOTE: This is beta, no alpha code. It is not ready.
+
+Below are some examples. To test them mark an example and do
+
+ M-x chartg-make-chart
+
+* Example, simple x-y chart:
+
+ Output-file: \"~/temp-chart.png\"
+ Size: 200 200
+ Data: 3 8 5 | 10 20 30
+ Type: line-chartg-xy
+
+* Example, pie:
+
+ Output-file: \"~/temp-depression.png\"
+ Size: 400 200
+ Data:
+ 2,160,000
+ 3,110,000
+ 1,510,000
+ 73,600
+ 775,000
+ 726,000
+ 8,180,000
+ 419,000
+ Type: pie-3-dimensional
+ Chartg-title: \"Depression hits on Google\"
+ Legends:
+ \"SSRI\"
+ | \"Psychotherapy\"
+ | \"CBT\"
+ | \"IPT\"
+ | \"Psychoanalysis\"
+ | \"Mindfulness\"
+ | \"Meditation\"
+ | \"Exercise\"
+
+
+* Example, pie:
+
+ Output-file: \"~/temp-panic.png\"
+ Size: 400 200
+ Data:
+ 979,000
+ 969,000
+ 500,000
+ 71,900
+ 193,000
+ 154,000
+ 2,500,000
+ 9,310,000
+ Type: pie-3-dimensional
+ Chartg-title: \"Depression hits on Google\"
+ Legends:
+ \"SSRI\"
+ | \"Psychotherapy\"
+ | \"CBT\"
+ | \"IPT\"
+ | \"Psychoanalysis\"
+ | \"Mindfulness\"
+ | \"Meditation\"
+ | \"Exercise\"
+
+
+* Example using raw:
+
+ Output-file: \"~/temp-chartg-slipsen-kostar.png\"
+ Size: 400 130
+ Data: 300 1000 30000
+ Type: bar-chartg-horizontal
+ Chartg-title: \"Vad killen i slips tjänar jämfört med dig och mig\"
+ Google-chartg-raw: \"&chds=0,30000&chco=00cd00|ff4500|483d8b&chxt=y,x&chxl=0:|Killen+i+slips|Partiledarna|Du+och+jag&chf=bg,s,ffd700\"
+
+
+"
+ (interactive)
+ (if mark-active
+ (let* ((rb (region-beginning))
+ (re (region-end))
+ (data (buffer-substring-no-properties rb re))
+ (buf (generate-new-buffer "*Chart from region*")))
+ (switch-to-buffer buf)
+ (insert data)
+ (chartg-mode))
+ (unless (eq major-mode 'chartg-mode)
+ (switch-to-buffer (generate-new-buffer "*Chart*"))
+ (chartg-mode)))
+ (chartg-get-state nil))
+
+;; (defun chartg-from-region (min max)
+;; "Try to make a new chart from data in selected region.
+;; See `chartg-mode' for examples you can test with this function."
+;; (interactive "r")
+;; (unless mark-active (error "No region selected"))
+;; (let* ((rb (region-beginning))
+;; (re (region-end))
+;; (data (buffer-substring-no-properties rb re))
+;; (buf (generate-new-buffer "*Chart from region*")))
+;; (switch-to-buffer buf)
+;; (insert data)
+;; (chartg-mode)
+;; (chartg-get-state nil)))
+
+(define-derived-mode chartg-mode fundamental-mode "Chart"
+ "Mode for specifying charts.
+\\{chartg-mode-map}
+
+To make a chart see `chartg-make-chart'.
+
+"
+ (set (make-local-variable 'font-lock-defaults) chartg-font-lock-defaults)
+ (set (make-local-variable 'comment-start) ";")
+ ;; Look within the line for a ; following an even number of backslashes
+ ;; after either a non-backslash or the line beginning.
+ (set (make-local-variable 'comment-start-skip)
+ "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
+ ;; Font lock mode uses this only when it KNOWS a comment is starting.
+ (set (make-local-variable 'font-lock-comment-start-skip) ";+ *")
+ (set (make-local-variable 'comment-add) 1) ;default to `;;' in comment-region
+ (set (make-local-variable 'comment-column) 40)
+ ;; Don't get confused by `;' in doc strings when paragraph-filling.
+ (set (make-local-variable 'comment-use-global-state) t)
+ (set-syntax-table chartg-mode-syntax-table)
+ (when (looking-at (rx buffer-start (0+ whitespace) buffer-end))
+ (insert ";; Type C-c C-c to make a chart, M-Tab to complete\n"))
+ (let ((missing (chartg-missing-keywords)))
+ (when missing
+ (save-excursion
+ (goto-char (point-max))
+ (dolist (miss missing)
+ (insert "\n" miss " "))))))
+
+;; Tests
+;;(chartg-create 'google "temp.png" '(200 . 150) '(((90 70) . nil)) 'pie-3-dimensional "test title" nil '((colors "FFFFFF" "00FF00")))
+
+;; Fix-me
+(add-to-list 'auto-mode-alist '("\\.mx-chart\\'" . chartg-mode))
+
+(provide 'chartg)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; chartg.el ends here