changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > infra > home / annotate .emacs.d/lib/eplot.el

changeset 97: f61dc77440df
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 08 Sep 2024 20:46:10 -0400
permissions: -rw-r--r--
description: add eplot.el
97
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1
 ;;; eplot.el --- Manage and Edit Wordpress Posts -*- lexical-binding: t -*-
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3
 ;; Copyright (C) 2024 Free Software Foundation, Inc.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
4
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
5
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
6
 ;; Keywords: charts
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
7
 ;; Package: eplot
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
8
 ;; Version: 1.0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
9
 ;; Package-Requires: ((emacs "29.0.59") (pcsv "0.0"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
10
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
11
 ;; eplot is free software; you can redistribute it and/or modify it
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
12
 ;; under the terms of the GNU General Public License as published by
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
13
 ;; the Free Software Foundation; either version 2, or (at your option)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
14
 ;; any later version.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
15
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
16
 ;;; Commentary:
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
17
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
18
 ;; The main entry point is `M-x eplot' in a buffer with time series
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
19
 ;; data.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
20
 ;;
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
21
 ;; If installing manually, put something like the following in your
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
22
 ;; Emacs init file (but adjust the path to where you've put eplot):
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
23
 ;; 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
24
 ;; (push "~/src/eplot/" load-path)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
25
 ;; (autoload 'eplot "eplot" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
26
 ;; (autoload 'eplot-mode "eplot" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
27
 ;; (unless (assoc "\\.plt" auto-mode-alist)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
28
 ;;   (setq auto-mode-alist (cons '("\\.plt" . eplot-mode) auto-mode-alist)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
29
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
30
 ;; This requires the pcsv package to parse CSV files.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
31
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
32
 ;;; Code:
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
33
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
34
 (require 'svg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
35
 (require 'cl-lib)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
36
 (require 'face-remap)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
37
 (require 'eieio)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
38
 (require 'iso8601)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
39
 (require 'transient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
40
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
41
 (defvar eplot--user-defaults nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
42
 (defvar eplot--chart-headers nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
43
 (defvar eplot--plot-headers nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
44
 (defvar eplot--transient-settings nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
45
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
46
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
47
 (defvar eplot--colors
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
48
   '("aliceblue" "antiquewhite" "aqua" "aquamarine" "azure" "beige" "bisque"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
49
     "black" "blanchedalmond" "blue" "blueviolet" "brown" "burlywood"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
50
     "cadetblue" "chartreuse" "chocolate" "coral" "cornflowerblue" "cornsilk"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
51
     "crimson" "cyan" "darkblue" "darkcyan" "darkgoldenrod" "darkgray"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
52
     "darkgreen" "darkgrey" "darkkhaki" "darkmagenta" "darkolivegreen"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
53
     "darkorange" "darkorchid" "darkred" "darksalmon" "darkseagreen"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
54
     "darkslateblue" "darkslategray" "darkslategrey" "darkturquoise"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
55
     "darkviolet" "deeppink" "deepskyblue" "dimgray" "dimgrey" "dodgerblue"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
56
     "firebrick" "floralwhite" "forestgreen" "fuchsia" "gainsboro" "ghostwhite"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
57
     "gold" "goldenrod" "gray" "green" "greenyellow" "grey" "honeydew" "hotpink"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
58
     "indianred" "indigo" "ivory" "khaki" "lavender" "lavenderblush" "lawngreen"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
59
     "lemonchiffon" "lightblue" "lightcoral" "lightcyan" "lightgoldenrodyellow"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
60
     "lightgray" "lightgreen" "lightgrey" "lightpink" "lightsalmon"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
61
     "lightseagreen" "lightskyblue" "lightslategray" "lightslategrey"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
62
     "lightsteelblue" "lightyellow" "lime" "limegreen" "linen" "magenta"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
63
     "maroon" "mediumaquamarine" "mediumblue" "mediumorchid" "mediumpurple"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
64
     "mediumseagreen" "mediumslateblue" "mediumspringgreen" "mediumturquoise"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
65
     "mediumvioletred" "midnightblue" "mintcream" "mistyrose" "moccasin"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
66
     "navajowhite" "navy" "oldlace" "olive" "olivedrab" "orange" "orangered"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
67
     "orchid" "palegoldenrod" "palegreen" "paleturquoise" "palevioletred"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
68
     "papayawhip" "peachpuff" "peru" "pink" "plum" "powderblue" "purple" "red"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
69
     "rosybrown" "royalblue" "saddlebrown" "salmon" "sandybrown" "seagreen"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
70
     "seashell" "sienna" "silver" "skyblue" "slateblue" "slategray" "slategrey"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
71
     "snow" "springgreen" "steelblue" "tan" "teal" "thistle" "tomato"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
72
     "turquoise" "violet" "wheat" "white" "whitesmoke" "yellow" "yellowgreen"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
73
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
74
 (defun eplot-set (header value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
75
   "Set the default value of HEADER to VALUE.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
76
 To get a list of all possible HEADERs, use the `M-x
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
77
 eplot-list-chart-headers' command.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
78
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
79
 Also see `eplot-reset'."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
80
   (let ((elem (or (assq header eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
81
 		  (assq header eplot--plot-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
82
     (unless elem
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
83
       (error "No such header type: %s" header))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
84
     (eplot--add-default header value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
85
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
86
 (defun eplot--add-default (header value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
87
   ;; We want to preserve the order defaults have been added, so that
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
88
   ;; we can apply them in the same order.  This makes a difference
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
89
   ;; when we're dealing with specs that have inheritence.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
90
   (setq eplot--user-defaults (delq (assq header eplot--user-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
91
 				   eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
92
   (setq eplot--user-defaults (list (cons header value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
93
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
94
 (defun eplot-reset (&optional header)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
95
   "Reset HEADER to defaults.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
96
 If HEADER is nil or not present, reset everything to defaults."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
97
   (if header
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
98
       (setq eplot--user-defaults (delq (assq header eplot--user-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
99
 				       eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
100
     (setq eplot--user-defaults nil)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
101
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
102
 (unless (assoc "\\.plt" auto-mode-alist)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
103
   (setq auto-mode-alist (cons '("\\.plt" . eplot-mode) auto-mode-alist)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
104
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
105
 ;;; eplot modes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
106
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
107
 (defvar-keymap eplot-mode-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
108
   "C-c C-c" #'eplot-update-view-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
109
   "C-c C-p" #'eplot-switch-view-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
110
   "C-c C-e" #'eplot-list-chart-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
111
   "C-c C-v" #'eplot-customize
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
112
   "C-c C-l" #'eplot-create-controls
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
113
   "TAB" #'eplot-complete)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
114
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
115
 ;; # is working overtime in the syntax here:
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
116
 ;;  It can be a color like Color: #e0e0e0, and
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
117
 ;;  it can be a setting like 33 # Label: Apples,
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
118
 ;;  when it starts a line it's a comment.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
119
 (defvar eplot-font-lock-keywords
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
120
   `(("^[ \t\n]*#.*" . font-lock-comment-face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
121
     ("^[^ :\n]+:" . font-lock-keyword-face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
122
     ("#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\\)?" . font-lock-variable-name-face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
123
     ("#.*" . font-lock-builtin-face)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
124
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
125
 (define-derived-mode eplot-mode text-mode "eplot"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
126
   "Major mode for editing charts.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
127
 Use the \\[eplot-list-chart-headers] command to get a list of all
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
128
 possible chart headers."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
129
   (setq-local completion-at-point-functions
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
130
 	      (cons 'eplot--complete-header completion-at-point-functions))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
131
   (setq-local font-lock-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
132
 	      '(eplot-font-lock-keywords nil nil nil)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
133
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
134
 (defun eplot-complete ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
135
   "Complete headers."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
136
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
137
   (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
138
    ((let ((completion-fail-discreetly t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
139
       (completion-at-point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
140
     ;; Completion was performed; nothing else to do.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
141
     nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
142
    (t (indent-relative))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
143
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
144
 (defun eplot--complete-header ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
145
   (or
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
146
    ;; Complete headers names.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
147
    (and (or (looking-at ".*:")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
148
 	    (and (looking-at "[ \t]*$")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
149
 		 (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
150
 		   (beginning-of-line)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
151
 		   (not (looking-at "\\(.+\\):")))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
152
 	(lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
153
 	  (let ((headers (mapcar
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
154
 			  (lambda (h)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
155
 			    (if (looking-at ".*:")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
156
 				(capitalize (symbol-name (car h)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
157
 			      (concat (capitalize (symbol-name (car h))) ": ")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
158
 			  (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
159
 			    ;; If we're after the headers, then we want
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
160
 			    ;; to complete over the plot headers.  Otherwise,
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
161
 			    ;; complete over the chart headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
162
 			    (if (and (not (bobp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
163
 				     (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
164
 				       (forward-line -1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
165
 				       (re-search-backward "^[ \t]*$" nil t)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
166
 				eplot--plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
167
 			      eplot--chart-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
168
 		(completion-ignore-case t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
169
 	    (completion-in-region (pos-bol) (line-end-position) headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
170
 	    'completion-attempted)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
171
    ;; Complete header values.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
172
    (let ((hname nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
173
      (and (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
174
 	    (and (looking-at "[ \t]*$")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
175
 		 (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
176
 		   (beginning-of-line)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
177
 		   (and (looking-at "\\(.+\\):")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
178
 			(setq hname (intern (downcase (match-string 1)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
179
 	    (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
180
 	      (let ((valid (plist-get
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
181
 			    (cdr (assq hname (append eplot--plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
182
 						     eplot--chart-headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
183
 			    :valid))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
184
 		    (completion-ignore-case t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
185
 		(completion-in-region
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
186
 		 (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
187
 		   (search-backward ":" (pos-bol) t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
188
 		   (skip-chars-forward ": \t")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
189
 		   (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
190
 		 (line-end-position)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
191
 		 (mapcar #'symbol-name valid))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
192
 		'completion-attempted)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
193
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
194
 (define-minor-mode eplot-minor-mode
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
195
   "Minor mode to issue commands from an eplot data buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
196
   :lighter " eplot")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
197
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
198
 (defvar-keymap eplot-minor-mode-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
199
   "H-l" #'eplot-eval-and-update)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
200
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
201
 (defvar-keymap eplot-view-mode-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
202
   "s" #'eplot-view-write-file
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
203
   "w" #'eplot-view-write-scaled-file
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
204
   "c" #'eplot-view-customize
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
205
   "l" #'eplot-create-controls)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
206
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
207
 (define-derived-mode eplot-view-mode special-mode "eplot view"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
208
   "Major mode for displaying eplots."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
209
   (setq-local revert-buffer-function #'eplot-update
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
210
 	      cursor-type nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
211
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
212
 (defun eplot-view-write-file (file &optional width)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
213
   "Write the current chart to a file.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
214
 If you type in a file name that ends with something else than \"svg\",
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
215
 ImageMagick \"convert\" will be used to convert the image first.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
216
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
217
 If writing to a PNG file, \"rsvg-conver\" will be used instead if
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
218
 it exists as this usually gives better results."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
219
   (interactive "FWrite to file name: ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
220
   (when (and (file-exists-p file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
221
 	     (not (yes-or-no-p "File exists, overwrite? ")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
222
     (error "Not overwriting the file"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
223
   (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
224
     (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
225
     (let ((match
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
226
 	   (text-property-search-forward 'display nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
227
 					 (lambda (_ e)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
228
 					   (and (consp e)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
229
 						(eq (car e) 'image))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
230
       (unless match
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
231
 	(error "Can't find an image in the current buffer"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
232
       (let ((svg (plist-get (cdr (prop-match-value match)) :data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
233
 	    (tmp " *eplot convert*")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
234
 	    (executable (if width "rsvg-convert" "convert"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
235
 	    sfile ofile)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
236
 	(unless svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
237
 	  (error "Invalid image in the current buffer"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
238
 	(with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
239
 	  (set-buffer-multibyte nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
240
 	  (svg-print svg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
241
 	  (if (string-match-p "\\.svg\\'" file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
242
 	      (write-region (point-min) (point-max) file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
243
 	    (if (and (string-match-p "\\.png\\'" file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
244
 		     (executable-find "rsvg-convert"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
245
 		(setq executable "rsvg-convert")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
246
 	      (unless (executable-find executable)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
247
 		(error "%s isn't installed; can only save svg files"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
248
 		       executable)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
249
 	    (when (and (equal executable "rsvg-convert")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
250
 		       (not (string-match-p "\\.png\\'" file))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
251
 		       (not (executable-find "convert")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
252
 	      (error "Can only write PNG files when scaling because \"convert\" isn't installed"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
253
 	    (unwind-protect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
254
 		(progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
255
 		  (setq sfile (make-temp-file "eplot" nil ".svg")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
256
 			ofile (make-temp-file "eplot" nil ".png"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
257
 		  (write-region (point-min) (point-max) sfile nil 'silent)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
258
 		  ;; We don't use `call-process-region', because
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
259
 		  ;; convert doesn't seem to like that?
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
260
 		  (let ((code (if (equal executable "rsvg-convert")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
261
 				  (apply
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
262
 				   #'call-process
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
263
 				   executable nil (get-buffer-create tmp) nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
264
 				   `(,(format "--output=%s"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
265
 					      (expand-file-name ofile))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
266
 				     ,@(and width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
267
 					    `(,(format "--width=%d" width)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
268
 					      "--keep-aspect-ratio"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
269
 				     ,sfile))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
270
 				(call-process
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
271
 				 executable nil (get-buffer-create tmp) nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
272
 				 sfile file))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
273
 		    (eplot--view-error code tmp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
274
 		    (when (file-exists-p ofile)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
275
 		      (if (string-match-p "\\.png\\'" file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
276
 			  (rename-file ofile file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
277
 			(let ((code (call-process "convert" nil tmp nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
278
 						  ofile file)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
279
 			  (eplot--view-error code tmp))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
280
 		    (message "Wrote %s" file)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
281
 	      ;; Clean-up.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
282
 	      (when (get-buffer tmp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
283
 		(kill-buffer tmp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
284
 	      (when (file-exists-p sfile)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
285
 		(delete-file sfile))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
286
 	      (when (file-exists-p ofile)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
287
 		(delete-file sfile)))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
288
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
289
 (defun eplot--view-error (code tmp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
290
   (unless (zerop code)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
291
     (error "Error code %d: %s"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
292
 	   code
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
293
 	   (with-current-buffer tmp
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
294
 	     (while (search-forward "[ \t\n]+" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
295
 	       (replace-match " "))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
296
 	     (string-trim (buffer-string))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
297
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
298
 (defun eplot-view-write-scaled-file (width file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
299
   "Write the current chart to a rescaled to a file.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
300
 The rescaling is done by \"rsvg-convert\", which has to be
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
301
 installed.  Rescaling is done when rendering, so this should give
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
302
 you a clear, non-blurry version of the chart at any size."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
303
   (interactive "nWidth: \nFWrite to file: ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
304
   (eplot-view-write-file file width))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
305
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
306
 (defun eplot-view-customize ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
307
   "Customize the settings for the chart in the current buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
308
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
309
   (with-suppressed-warnings ((interactive-only eplot-customize))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
310
     (eplot-customize)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
311
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
312
 (defvar eplot--data-buffer nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
313
 (defvar eplot--current-chart nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
314
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
315
 (defun eplot ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
316
   "Plot the data in the current buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
317
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
318
   (eplot-update-view-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
319
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
320
 (defun eplot-with-headers (header-file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
321
   "Plot the data in the current buffer using headers from a file."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
322
   (interactive "fHeader file: ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
323
   (eplot-update-view-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
324
    (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
325
      (insert-file-contents header-file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
326
      (eplot--parse-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
327
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
328
 (defun eplot-switch-view-buffer ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
329
   "Switch to the eplot view buffer and render the chart."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
330
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
331
   (eplot-update-view-buffer nil t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
332
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
333
 (defun eplot-update-view-buffer (&optional headers switch)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
334
   "Update the eplot view buffer based on the current data buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
335
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
336
   ;; This is mainly useful during implementation.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
337
   (if (and (eq major-mode 'emacs-lisp-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
338
 	   (get-buffer-window "*eplot*" t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
339
       (with-current-buffer "*eplot*"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
340
 	(eplot-update)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
341
 	(when-let ((win (get-buffer-window "*eplot*" t)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
342
 	  (set-window-point win (point-min))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
343
     ;; Normal case.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
344
     (let* ((eplot--user-defaults (eplot--settings-table))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
345
 	   (data (eplot--parse-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
346
 	   (data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
347
 	   (window (selected-window)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
348
       (unless data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
349
 	(user-error "No data in the current buffer"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
350
       (setq data (eplot--inject-headers data headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
351
       (if (get-buffer-window "*eplot*" t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
352
 	  (set-buffer "*eplot*")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
353
 	(if switch
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
354
 	    (pop-to-buffer-same-window "*eplot*")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
355
 	  (pop-to-buffer "*eplot*")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
356
       (let ((inhibit-read-only t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
357
 	(erase-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
358
 	(unless (eq major-mode 'eplot-view-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
359
 	  (eplot-view-mode))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
360
 	(setq-local eplot--data-buffer data-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
361
 	(let ((chart (eplot--render data)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
362
 	  (with-current-buffer data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
363
 	    (setq-local eplot--current-chart chart)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
364
 	(insert "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
365
 	(when-let ((win (get-buffer-window "*eplot*" t)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
366
 	  (set-window-point win (point-min))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
367
       (select-window window))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
368
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
369
 (defun eplot--settings-table ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
370
   (if (not eplot--transient-settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
371
       eplot--user-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
372
     (append eplot--user-defaults eplot--transient-settings)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
373
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
374
 (defun eplot--inject-headers (data headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
375
   ;; It's OK not to separate the plot headers from the chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
376
   ;; headers.  Collect them here, if any.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
377
   (when-let ((plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
378
 	      (cl-loop for elem in (mapcar #'car eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
379
 		       for value = (eplot--vs elem headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
380
 		       when value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
381
 		       collect (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
382
 				 ;; Remove these headers from the data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
383
 				 ;; headers so that we don't get errors
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
384
 				 ;; on undefined headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
385
 				 (setq headers (delq (assq elem headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
386
 						     headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
387
 				 (cons elem value)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
388
     (dolist (plot (cdr (assq :plots data)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
389
       (let ((headers (assq :headers plot)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
390
 	(if headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
391
 	    (nconc headers plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
392
 	  (nconc plot (list (list :headers plot-headers)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
393
   (append data headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
394
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
395
 (defun eplot-eval-and-update ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
396
   "Helper command when developing."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
397
   (interactive nil emacs-lisp-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
398
   (save-some-buffers t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
399
   (elisp-eval-region-or-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
400
   (eval-defun nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
401
   (eplot-update-view-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
402
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
403
 ;;; Parsing buffers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
404
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
405
 (defun eplot-update (&rest _ignore)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
406
   "Update the plot in the current buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
407
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
408
   (unless eplot--data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
409
     (user-error "No data buffer associated with this eplot view buffer"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
410
   (let ((data (with-current-buffer eplot--data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
411
 		(eplot--parse-buffer)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
412
 	(eplot--user-defaults (with-current-buffer eplot--data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
413
 				(eplot--settings-table)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
414
 	(inhibit-read-only t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
415
     (erase-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
416
     (let ((chart (eplot--render data)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
417
       (with-current-buffer eplot--data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
418
 	(setq-local eplot--current-chart chart)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
419
     (insert "\n\n")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
420
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
421
 (defun eplot--parse-buffer ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
422
   (if (eq major-mode 'org-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
423
       (eplot--parse-org-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
424
     (eplot--parse-eplot-buffer)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
425
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
426
 (defun eplot--parse-eplot-buffer ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
427
   (if (eplot--csv-buffer-p)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
428
       (eplot--parse-csv-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
429
     (let ((buf (current-buffer)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
430
       (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
431
 	(insert-buffer-substring buf)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
432
 	;; Remove comments first.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
433
 	(goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
434
 	(while (re-search-forward "^[ \t]*#" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
435
 	  (delete-line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
436
 	(goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
437
 	;; First headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
438
 	(let* ((data (eplot--parse-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
439
 	       (plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
440
 		;; It's OK not to separate the plot headers from the chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
441
 		;; headers.  Collect them here, if any.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
442
 		(cl-loop for elem in (mapcar #'car eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
443
 			 for value = (eplot--vs elem data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
444
 			 when value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
445
 			 collect (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
446
 				   ;; Remove these headers from the data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
447
 				   ;; headers so that we don't get errors
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
448
 				   ;; on undefined headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
449
 				   (setq data (delq (assq elem data) data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
450
 				   (cons elem value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
451
 	       plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
452
 	  ;; Then the values.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
453
 	  (while-let ((plot (eplot--parse-values nil plot-headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
454
 	    (setq plot-headers nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
455
 	    (push plot plots))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
456
 	  (when plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
457
 	    (push (cons :plots (nreverse plots)) data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
458
 	  data)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
459
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
460
 (defun eplot--parse-headers ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
461
   (let ((data nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
462
 	type value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
463
     (while (looking-at "\\([^\n\t :]+\\):\\(.*\\)")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
464
       (setq type (intern (downcase (match-string 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
465
 	    value (substring-no-properties (string-trim (match-string 2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
466
       (forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
467
       ;; Get continuation lines.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
468
       (while (looking-at "[ \t]+\\(.*\\)")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
469
 	(setq value (concat value " " (string-trim (match-string 1))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
470
 	(forward-line 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
471
       (if (eq type 'header-file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
472
 	  (setq data (nconc data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
473
 			    (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
474
 			      (insert-file-contents value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
475
 			      (eplot--parse-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
476
 	;; We don't use `push' here because we want to preserve order
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
477
 	;; also when inserting headers from other files.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
478
 	(setq data (nconc data (list (cons type value))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
479
     data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
480
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
481
 (defun eplot--parse-values (&optional in-headers data-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
482
   ;; Skip past separator lines.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
483
   (while (looking-at "[ \t]*\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
484
     (forward-line 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
485
   (let* ((values nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
486
 	 ;; We may have plot-specific headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
487
 	 (headers (nconc (eplot--parse-headers) data-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
488
 	 (data-format (or (eplot--vyl 'data-format headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
489
 			  (eplot--vyl 'data-format in-headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
490
 	 (two-values (memq 'two-values data-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
491
 	 (xy (or (memq 'year data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
492
 		 (memq 'date data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
493
 		 (memq 'time data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
494
 		 (memq 'xy data-format)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
495
 	 (data-column (or (eplot--vn 'data-column headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
496
 			  (eplot--vn 'data-column in-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
497
     (if-let ((data-file (eplot--vs 'data-file headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
498
 	(with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
499
 	  (insert-file-contents data-file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
500
 	  (setq values (cdr (assq :values (eplot--parse-values headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
501
 		headers (delq (assq 'data headers) headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
502
       ;; Now we come to the data.  The data is typically either just a
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
503
       ;; number, or two numbers (in which case the first number is a
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
504
       ;; date or a time).  Labels ans settings can be introduced with
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
505
       ;; a # char.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
506
       (while (looking-at "\\([-0-9. \t]+\\)\\([ \t]*#\\(.*\\)\\)?")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
507
 	(let ((numbers (match-string 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
508
 	      (settings (eplot--parse-settings (match-string 3)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
509
 	      this)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
510
 	  (setq numbers (mapcar #'string-to-number
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
511
 				(split-string (string-trim numbers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
512
 	  ;; If we're reading two dimensionalish data, the first
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
513
 	  ;; number is the date/time/x.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
514
 	  (when xy
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
515
 	    (setq this (list :x (pop numbers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
516
 	  ;; Chop off all the numbers until we read the column(s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
517
 	  ;; we're using.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
518
 	  (when data-column
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
519
 	    (setq numbers (nthcdr (1- data-column) numbers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
520
 	  (when numbers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
521
 	    (setq this (nconc this (list :value (pop numbers)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
522
 	  (when two-values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
523
 	    (setq this (nconc this (list :extra-value (pop numbers)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
524
 	  (when settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
525
 	    (setq this (nconc this (list :settings settings))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
526
 	  (when (plist-get this :value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
527
 	    (push this values)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
528
 	(forward-line 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
529
       (setq values (nreverse values)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
530
     (and values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
531
 	 `((:headers . ,headers) (:values . ,values)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
532
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
533
 (defun eplot--parse-settings (string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
534
   (when string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
535
     (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
536
       (insert (string-trim string) "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
537
       (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
538
       (while (re-search-forward "\\(.\\)," nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
539
 	(if (equal (match-string 1) "\\")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
540
 	    (replace-match "," t t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
541
 	  (delete-char -1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
542
 	  (insert "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
543
 	  (when (looking-at "[ \t]+")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
544
 	    (replace-match ""))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
545
       (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
546
       (eplot--parse-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
547
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
548
 ;;; Accessing data.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
549
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
550
 (defun eplot--vn (type data &optional default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
551
   (if-let ((value (cdr (assq type data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
552
       (string-to-number value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
553
     default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
554
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
555
 (defun eplot--vs (type data &optional default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
556
   (or (cdr (assq type data)) default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
557
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
558
 (defun eplot--vy (type data &optional default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
559
   (if-let ((value (cdr (assq type data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
560
       (intern (downcase value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
561
     default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
562
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
563
 (defun eplot--vyl (type data &optional default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
564
   (if-let ((value (cdr (assq type data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
565
       (mapcar #'intern (split-string (downcase value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
566
     default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
567
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
568
 (defmacro eplot-def (args doc-string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
569
   (declare (indent defun))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
570
   `(eplot--def ',(nth 0 args) ',(nth 1 args) ',(nth 2 args) ',(nth 3 args)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
571
 	       ,doc-string))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
572
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
573
 (defun eplot--def (name type default valid doc)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
574
   (setq eplot--chart-headers (delq (assq name eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
575
 				   eplot--chart-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
576
   (push (list name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
577
 	      :type type
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
578
 	      :default default
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
579
 	      :doc doc
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
580
 	      :valid valid)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
581
 	eplot--chart-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
582
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
583
 (eplot-def (width number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
584
   "The width of the entire chart.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
585
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
586
 (eplot-def (height number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
587
   "The height of the entire chart.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
588
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
589
 (eplot-def (format symbol normal (normal bar-chart horizontal-bar-chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
590
   "The overall format of the chart.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
591
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
592
 (eplot-def (layout symbol nil (normal compact))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
593
   "The general layout of the chart.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
594
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
595
 (eplot-def (mode symbol light (dark light))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
596
   "Dark/light mode.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
597
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
598
 (eplot-def (margin-left number 70)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
599
   "The left margin.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
600
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
601
 (eplot-def (margin-right number 20)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
602
   "The right margin.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
603
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
604
 (eplot-def (margin-top number 40)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
605
   "The top margin.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
606
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
607
 (eplot-def (margin-bottom number 60)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
608
   "The bottom margin.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
609
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
610
 (eplot-def (x-axis-title-space number 5)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
611
   "The space between the X axis and the label.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
612
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
613
 (eplot-def (font string "sans-serif")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
614
   "The font to use in titles, labels and legends.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
615
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
616
 (eplot-def (font-size number 12)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
617
   "The font size.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
618
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
619
 (eplot-def (font-weight symbol bold (bold normal))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
620
   "The font weight.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
621
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
622
 (eplot-def (label-font string (spec font))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
623
   "The font to use for axes labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
624
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
625
 (eplot-def (label-font-size number (spec font-size))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
626
   "The font size to use for axes labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
627
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
628
 (eplot-def (bar-font string (spec font))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
629
   "The font to use for bar chart labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
630
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
631
 (eplot-def (bar-font-size number (spec font-size))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
632
   "The font size to use for bar chart labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
633
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
634
 (eplot-def (bar-font-weight symbol (spec font-weight) (bold normal))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
635
   "The font weight to use for bar chart labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
636
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
637
 (eplot-def (chart-color string "black")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
638
   "The foreground color to use in plots, axes, legends, etc.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
639
 This is used as the default, but can be overridden per thing.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
640
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
641
 (eplot-def (background-color string "white")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
642
   "The background color.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
643
 If you want a chart with a transparent background, use the color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
644
 \"none\".")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
645
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
646
 (eplot-def (background-gradient string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
647
   "Use this to get a gradient color in the background.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
648
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
649
 (eplot-def (axes-color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
650
   "The color of the axes.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
651
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
652
 (eplot-def (grid-color string "#e0e0e0")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
653
   "The color of the grid.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
654
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
655
 (eplot-def (grid symbol xy (xy x y off))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
656
   "What grid axes to do.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
657
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
658
 (eplot-def (grid-opacity number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
659
   "The opacity of the grid.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
660
 This should either be nil or a value between 0 and 1, where 0 is
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
661
 fully transparent.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
662
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
663
 (eplot-def (grid-position symbol bottom (bottom top))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
664
   "Whether to put the grid on top or under the plot.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
665
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
666
 (eplot-def (legend symbol nil (true nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
667
   "Whether to do a legend.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
668
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
669
 (eplot-def (legend-color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
670
   "The color of legends (if any).")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
671
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
672
 (eplot-def (legend-border-color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
673
   "The border color of legends (if any).")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
674
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
675
 (eplot-def (legend-background-color string (spec background-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
676
   "The background color of legends (if any).")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
677
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
678
 (eplot-def (label-color string (spec axes-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
679
   "The color of labels on the axes.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
680
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
681
 (eplot-def (surround-color string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
682
   "The color between the plot area and the edges of the chart.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
683
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
684
 (eplot-def (border-color string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
685
   "The color of the border of the chart, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
686
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
687
 (eplot-def (border-width number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
688
   "The width of the border of the chart, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
689
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
690
 (eplot-def (frame-color string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
691
   "The color of the frame of the plot, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
692
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
693
 (eplot-def (frame-width number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
694
   "The width of the frame of the plot, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
695
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
696
 (eplot-def (min number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
697
   "The minimum value in the chart.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
698
 This is normally computed automatically, but can be overridden
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
699
  with this spec.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
700
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
701
 (eplot-def (max number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
702
   "The maximum value in the chart.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
703
 This is normally computed automatically, but can be overridden
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
704
  with this spec.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
705
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
706
 (eplot-def (title string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
707
   "The title of the chart, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
708
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
709
 (eplot-def (title-color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
710
   "The color of the title.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
711
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
712
 (eplot-def (x-title string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
713
   "The title of the X axis, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
714
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
715
 (eplot-def (y-title string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
716
   "The title of the X axis, if any.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
717
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
718
 (eplot-def (x-label-format string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
719
   "Format string for the X labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
720
 This is a `format' string.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
721
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
722
 (eplot-def (y-label-format string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
723
   "Format string for the Y labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
724
 This is a `format' string.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
725
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
726
 (eplot-def (x-label-orientation symbol horizontal (horizontal vertical))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
727
   "Orientation of the X labels.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
728
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
729
 (eplot-def (background-image-file string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
730
   "Use an image as the background.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
731
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
732
 (eplot-def (background-image-opacity number 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
733
   "The opacity of the background image.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
734
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
735
 (eplot-def (background-image-cover symbol all (all plot frame))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
736
   "Position of the background image.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
737
 Valid values are `all' (the entire image), `plot' (the plot area)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
738
 and `frame' (the surrounding area).")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
739
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
740
 (eplot-def (header-file string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
741
   "File where the headers are.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
742
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
743
 (defvar eplot-compact-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
744
   '((margin-left 30)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
745
     (margin-right 10)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
746
     (margin-top 20)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
747
     (margin-bottom 21)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
748
     (font-size 12)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
749
     (x-axis-title-space 3)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
750
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
751
 (defvar eplot-dark-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
752
   '((chart-color "#c0c0c0")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
753
     (axes-color "#c0c0c0")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
754
     (grid-color "#404040")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
755
     (background-color "#101010")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
756
     (label-color "#c0c0c0")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
757
     (legend-color "#c0c0c0")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
758
     (title-color "#c0c0c0")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
759
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
760
 (defvar eplot-bar-chart-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
761
   '((grid-position top)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
762
     (grid y)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
763
     (grid-opacity 0.2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
764
     (min 0)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
765
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
766
 (defvar eplot-horizontal-bar-chart-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
767
   '((grid-position top)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
768
     (grid-opacity 0.2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
769
     (min 0)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
770
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
771
 (defclass eplot-chart ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
772
   (
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
773
    (plots :initarg :plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
774
    (data :initarg :data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
775
    (xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
776
    (ys)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
777
    (x-values :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
778
    (x-type :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
779
    (x-min)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
780
    (x-max)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
781
    (x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
782
    (y-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
783
    (y-labels)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
784
    (x-labels)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
785
    (print-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
786
    (x-tick-step)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
787
    (x-label-step)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
788
    (x-step-map :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
789
    (y-tick-step)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
790
    (y-label-step)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
791
    (inhibit-compute-x-step :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
792
    ;; ---- CUT HERE ----
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
793
    (axes-color :initarg :axes-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
794
    (background-color :initarg :background-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
795
    (background-gradient :initarg :background-gradient :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
796
    (background-image-cover :initarg :background-image-cover :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
797
    (background-image-file :initarg :background-image-file :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
798
    (background-image-opacity :initarg :background-image-opacity :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
799
    (bar-font :initarg :bar-font :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
800
    (bar-font-size :initarg :bar-font-size :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
801
    (bar-font-weight :initarg :bar-font-weight :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
802
    (border-color :initarg :border-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
803
    (border-width :initarg :border-width :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
804
    (chart-color :initarg :chart-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
805
    (font :initarg :font :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
806
    (font-size :initarg :font-size :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
807
    (font-weight :initarg :font-weight :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
808
    (format :initarg :format :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
809
    (frame-color :initarg :frame-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
810
    (frame-width :initarg :frame-width :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
811
    (grid :initarg :grid :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
812
    (grid-color :initarg :grid-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
813
    (grid-opacity :initarg :grid-opacity :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
814
    (grid-position :initarg :grid-position :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
815
    (header-file :initarg :header-file :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
816
    (height :initarg :height :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
817
    (label-color :initarg :label-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
818
    (label-font :initarg :label-font :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
819
    (label-font-size :initarg :label-font-size :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
820
    (layout :initarg :layout :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
821
    (legend :initarg :legend :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
822
    (legend-background-color :initarg :legend-background-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
823
    (legend-border-color :initarg :legend-border-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
824
    (legend-color :initarg :legend-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
825
    (margin-bottom :initarg :margin-bottom :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
826
    (margin-left :initarg :margin-left :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
827
    (margin-right :initarg :margin-right :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
828
    (margin-top :initarg :margin-top :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
829
    (max :initarg :max :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
830
    (min :initarg :min :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
831
    (mode :initarg :mode :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
832
    (surround-color :initarg :surround-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
833
    (title :initarg :title :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
834
    (title-color :initarg :title-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
835
    (width :initarg :width :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
836
    (x-axis-title-space :initarg :x-axis-title-space :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
837
    (x-title :initarg :x-title :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
838
    (y-title :initarg :y-title :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
839
    (x-label-format :initarg :x-label-format :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
840
    (x-label-orientation :initarg :x-label-orientation :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
841
    (y-label-format :initarg :y-label-format :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
842
    ;; ---- CUT HERE ----
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
843
    ))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
844
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
845
 ;;; Parameters that are plot specific.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
846
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
847
 (defmacro eplot-pdef (args doc-string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
848
   (declare (indent defun))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
849
   `(eplot--pdef ',(nth 0 args) ',(nth 1 args) ',(nth 2 args) ',(nth 3 args)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
850
 		,doc-string))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
851
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
852
 (defun eplot--pdef (name type default valid doc)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
853
   (setq eplot--plot-headers (delq (assq name eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
854
 				   eplot--plot-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
855
   (push (list name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
856
 	      :type type
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
857
 	      :default default
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
858
 	      :valid valid
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
859
 	      :doc doc)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
860
 	eplot--plot-headers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
861
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
862
 (eplot-pdef (smoothing symbol nil (moving-average nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
863
   "Smoothing algorithm to apply to the data, if any.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
864
 Valid values are `moving-average' and, er, probably more to come.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
865
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
866
 (eplot-pdef (gradient string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
867
   "Gradient to apply to the plot.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
868
 The syntax is:
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
869
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
870
   from-color to-color direction position
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
871
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
872
 The last two parameters are optional.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
873
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
874
 direction is either `top-down' (the default), `bottom-up',
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
875
 `left-right' or `right-left').
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
876
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
877
 position is either `below' or `above'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
878
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
879
 to-color can be either a color name, or a string that defines
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
880
 stops and colors:
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
881
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
882
    Gradient: black 25-purple-50-white-75-purple-black
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
883
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
884
 In that case, the second element specifies the percentage points
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
885
 of where each color ends, so the above starts with black, then at
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
886
 25% it's purple, then at 50% it's white, then it's back to purple
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
887
 again at 75%, before ending up at black at a 100% (but you don't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
888
 have to include the 100% here -- it's understood).")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
889
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
890
 (eplot-pdef (style symbol line ( line impulse point square circle cross
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
891
 				 triangle rectangle curve))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
892
   "Style the plot should be drawn in.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
893
 Valid values are listed below.  Some styles take additional
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
894
 optional parameters.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
895
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
896
 line
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
897
   Straight lines between values.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
898
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
899
 curve
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
900
   Curved lines between values.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
901
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
902
 impulse
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
903
   size: width of the impulse
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
904
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
905
 point
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
906
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
907
 square
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
908
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
909
 circle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
910
   size: diameter of the circle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
911
   fill-color: color to fill the center
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
912
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
913
 cross
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
914
   size: length of the lines in the cross
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
915
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
916
 triangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
917
   size: length of the sides of the triangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
918
   fill-color: color to fill the center
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
919
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
920
 rectangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
921
   size: length of the sides of the rectangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
922
   fill-color: color to fill the center")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
923
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
924
 (eplot-pdef (fill-color string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
925
   "Color to use to fill the plot styles that are closed shapes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
926
 I.e., circle, triangle and rectangle.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
927
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
928
 (eplot-pdef (color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
929
   "Color to draw the plot.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
930
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
931
 (eplot-pdef (data-format symbol single (single date time xy))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
932
   "Format of the data.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
933
 By default, eplot assumes that each line has a single data point.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
934
 This can also be `date', `time' and `xy'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
935
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
936
 date: The first column is a date on ISO8601 format (i.e., YYYYMMDD).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
937
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
938
 time: The first column is a clock (i.e., HHMMSS).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
939
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
940
 xy: The first column is the X position.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
941
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
942
 (eplot-pdef (data-column number 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
943
   "Column where the data is.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
944
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
945
 (eplot-pdef (fill-border-color string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
946
   "Border around the fill area when using a fill/gradient style.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
947
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
948
 (eplot-pdef (size number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
949
   "Size of elements in styles that have meaningful sizes.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
950
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
951
 (eplot-pdef (size-factor number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
952
   "Multiply the size of the elements by the value.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
953
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
954
 (eplot-pdef (data-file string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
955
   "File where the data is.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
956
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
957
 (eplot-pdef (data-format symbol-list nil (nil two-values date time))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
958
   "List of symbols to describe the data format.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
959
 Elements allowed are `two-values', `date' and `time'.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
960
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
961
 (eplot-pdef (name string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
962
   "Name of the plot, which will be displayed if legends are switched on.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
963
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
964
 (eplot-pdef (legend-color string (spec chart-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
965
   "Color for the name to be displayed in the legend.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
966
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
967
 (eplot-pdef (bezier-factor number 0.1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
968
   "The Bezier factor to apply to curve plots.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
969
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
970
 (defclass eplot-plot ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
971
   (
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
972
    (values :initarg :values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
973
    ;; ---- CUT HERE ----
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
974
    (bezier-factor :initarg :bezier-factor :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
975
    (color :initarg :color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
976
    (data-column :initarg :data-column :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
977
    (data-file :initarg :data-file :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
978
    (data-format :initarg :data-format :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
979
    (fill-border-color :initarg :fill-border-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
980
    (fill-color :initarg :fill-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
981
    (gradient :initarg :gradient :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
982
    (legend-color :initarg :legend-color :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
983
    (name :initarg :name :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
984
    (size :initarg :size :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
985
    (size-factor :initarg :size-factor :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
986
    (smoothing :initarg :smoothing :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
987
    (style :initarg :style :initform nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
988
    ;; ---- CUT HERE ----
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
989
    ))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
990
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
991
 (defun eplot--make-plot (data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
992
   "Make an `eplot-plot' object and initialize based on DATA."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
993
   (let ((plot (make-instance 'eplot-plot
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
994
 			     :values (cdr (assq :values data)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
995
     ;; Get the program-defined defaults.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
996
     (eplot--object-defaults plot eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
997
     ;; One special case.  I don't think this hack is quite right...
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
998
     (when (or (eq (eplot--vs 'mode data) 'dark)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
999
 	      (eq (cdr (assq 'mode eplot--user-defaults)) 'dark))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1000
       (setf (slot-value plot 'color) "#c0c0c0"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1001
     ;; Use the headers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1002
     (eplot--object-values plot (cdr (assq :headers data)) eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1003
     plot))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1004
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1005
 (defun eplot--make-chart (data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1006
   "Make an `eplot-chart' object and initialize based on DATA."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1007
   (let ((chart (make-instance 'eplot-chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1008
 			      :plots (mapcar #'eplot--make-plot
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1009
 					     (eplot--vs :plots data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1010
 			      :data data)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1011
     ;; First get the program-defined defaults.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1012
     (eplot--object-defaults chart eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1013
     ;; Then do the "meta" variables.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1014
     (eplot--meta chart data 'mode 'dark eplot-dark-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1015
     (eplot--meta chart data 'layout 'compact eplot-compact-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1016
     (eplot--meta chart data 'format 'bar-chart eplot-bar-chart-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1017
     (eplot--meta chart data 'format 'horizontal-bar-chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1018
 		 eplot-horizontal-bar-chart-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1019
     ;; Set defaults from user settings/transients.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1020
     (cl-loop for (name . value) in eplot--user-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1021
 	     when (assq name eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1022
 	     do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1023
 	     (setf (slot-value chart name) value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1024
 	     (eplot--set-dependent-values chart name value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1025
     ;; Finally, use the data from the chart.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1026
     (eplot--object-values chart data eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1027
     ;; If not set, recompute the margins based on the font sizes (if
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1028
     ;; the font size has been changed from defaults).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1029
     (when (or (assq 'font-size eplot--user-defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1030
 	      (assq 'font-size data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1031
       (with-slots ( title x-title y-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1032
 		    margin-top margin-bottom margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1033
 		    font-size font font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1034
 	  chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1035
 	(when (or title x-title y-title)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1036
 	  (let ((text-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1037
 		 (eplot--text-height (concat title x-title y-title)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1038
 				     font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1039
 	    (when (and title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1040
 		       (and (not (assq 'margin-top eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1041
 			    (not (assq 'margin-top data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1042
 	      (cl-incf margin-top (* text-height 1.4)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1043
 	    (when (and x-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1044
 		       (and (not (assq 'margin-bottom eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1045
 			    (not (assq 'margin-bottom data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1046
 	      (cl-incf margin-bottom (* text-height 1.4)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1047
 	    (when (and y-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1048
 		       (and (not (assq 'margin-left eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1049
 			    (not (assq 'margin-left data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1050
 	      (cl-incf margin-left (* text-height 1.4)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1051
     chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1052
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1053
 (defun eplot--meta (chart data slot value defaults)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1054
   (when (or (eq (cdr (assq slot eplot--user-defaults)) value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1055
 	    (eq (eplot--vy slot data) value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1056
     (eplot--set-theme chart defaults)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1057
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1058
 (defun eplot--object-defaults (object headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1059
   (dolist (header headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1060
     (when-let ((default (plist-get (cdr header) :default)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1061
       (setf (slot-value object (car header))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1062
 	    ;; Allow overrides via `eplot-set'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1063
 	    (or (cdr (assq (car header) eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1064
 		(if (and (consp default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1065
 			 (eq (car default) 'spec))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1066
 		    ;; Chase dependencies.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1067
 		    (eplot--default (cadr default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1068
 		  default))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1069
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1070
 (defun eplot--object-values (object data headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1071
   (cl-loop for (name . value) in data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1072
 	   do (unless (eq name :plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1073
 		(let ((spec (cdr (assq name headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1074
 		  (if (not spec)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1075
 		      (error "%s is not a valid spec" name)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1076
 		    (let ((value 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1077
 			   (cl-case (plist-get spec :type)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1078
 			     (number
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1079
 			      (string-to-number value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1080
 			     (symbol
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1081
 			      (intern (downcase value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1082
 			     (symbol-list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1083
 			      (mapcar #'intern (split-string (downcase value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1084
 			     (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1085
 			      value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1086
 		      (setf (slot-value object name) value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1087
 		      (eplot--set-dependent-values object name value)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1088
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1089
 (defun eplot--set-dependent-values (object name value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1090
   (dolist (slot (gethash name (eplot--dependecy-graph)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1091
     (setf (slot-value object slot) value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1092
     (eplot--set-dependent-values object slot value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1093
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1094
 (defun eplot--set-theme (chart map)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1095
   (cl-loop for (slot value) in map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1096
 	   do (setf (slot-value chart slot) value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1097
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1098
 (defun eplot--default (slot)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1099
   "Find the default value for SLOT, chasing dependencies."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1100
   (let ((spec (cdr (assq slot eplot--chart-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1101
     (unless spec
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1102
       (error "Invalid slot %s" slot))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1103
     (let ((default (plist-get spec :default)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1104
       (if (and (consp default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1105
 	       (eq (car default) 'spec))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1106
 	  (eplot--default (cadr default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1107
 	(or (cdr (assq slot eplot--user-defaults)) default)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1108
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1109
 (defun eplot--dependecy-graph ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1110
   (let ((table (make-hash-table)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1111
     (dolist (elem eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1112
       (let ((default (plist-get (cdr elem) :default)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1113
 	(when (and (consp default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1114
 		   (eq (car default) 'spec))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1115
 	  (push (car elem) (gethash (cadr default) table)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1116
     table))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1117
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1118
 (defun eplot--render (data &optional return-image)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1119
   "Create the chart and display it.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1120
 If RETURN-IMAGE is non-nil, return it instead of displaying it."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1121
   (let* ((chart (eplot--make-chart data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1122
 	 svg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1123
     (with-slots ( width height xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1124
 		  margin-left margin-right margin-top margin-bottom
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1125
 		  grid-position plots x-min format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1126
 		  x-label-orientation)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1127
 	chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1128
       ;; Set the size of the chart based on the window it's going to
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1129
       ;; be displayed in.  It uses the *eplot* window by default, or
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1130
       ;; the current one if that isn't displayed.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1131
       (let ((factor (image-compute-scaling-factor image-scaling-factor)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1132
 	(unless width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1133
 	  (setq width (truncate
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1134
 		       (/ (* (window-pixel-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1135
  			      (get-buffer-window "*eplot*" t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1136
 			     0.9)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1137
 			  factor))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1138
 	(unless height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1139
 	  (setq height (truncate
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1140
 			(/ (* (window-pixel-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1141
 			       (get-buffer-window "*eplot*" t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1142
 			      0.9)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1143
 			   factor)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1144
       (setq svg (svg-create width height)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1145
 	    xs (- width margin-left margin-right)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1146
 	    ys (- height margin-top margin-bottom))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1147
       ;; Protect against being called in an empty buffer.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1148
       (if (not (and plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1149
 		    ;; Sanity check against the user choosing dimensions
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1150
 		    ;; that leave no space for the plot.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1151
 		    (> ys 0) (> xs 0)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1152
 	  ;; Just draw the basics.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1153
 	  (eplot--draw-basics svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1154
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1155
 	;; Horizontal bar charts are special.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1156
 	(when (eq format 'horizontal-bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1157
 	  (eplot--adjust-horizontal-bar-chart chart data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1158
 	;; Compute min/max based on all plots, and also compute x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1159
 	;; etc.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1160
 	(eplot--compute-chart-dimensions chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1161
 	(when (and (eq x-label-orientation 'vertical)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1162
 		   (eplot--default-p 'margin-bottom (slot-value chart 'data)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1163
 	  (eplot--adjust-vertical-x-labels chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1164
 	;; Analyze values and adjust values accordingly.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1165
 	(eplot--adjust-chart chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1166
 	;; Compute the Y labels -- this may adjust `margin-left'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1167
 	(eplot--compute-y-labels chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1168
 	;; Compute the X labels -- this may adjust `margin-bottom'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1169
 	(eplot--compute-x-labels chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1170
 	;; Draw background/borders/titles/etc.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1171
 	(eplot--draw-basics svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1172
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1173
 	(when (eq grid-position 'top)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1174
 	  (eplot--draw-plots svg chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1175
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1176
 	(eplot--draw-x-ticks svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1177
 	(unless (eq format 'horizontal-bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1178
 	  (eplot--draw-y-ticks svg chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1179
       
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1180
 	;; Draw axes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1181
 	(with-slots ( margin-left margin-right margin-margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1182
 		      margin-bottom axes-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1183
 	    chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1184
 	  (svg-line svg margin-left margin-top margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1185
 		    (+ (- height margin-bottom) 5)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1186
 		    :stroke axes-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1187
 	  (svg-line svg (- margin-left 5) (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1188
 		    (- width margin-right) (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1189
 		    :stroke axes-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1190
     
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1191
 	(when (eq grid-position 'bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1192
 	  (eplot--draw-plots svg chart)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1193
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1194
       (with-slots (frame-color frame-width) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1195
 	(when (or frame-color frame-width)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1196
 	  (svg-rectangle svg margin-left margin-top xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1197
 			 :stroke-width frame-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1198
 			 :fill "none"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1199
 			 :stroke-color frame-color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1200
       (eplot--draw-legend svg chart))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1201
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1202
     (if return-image
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1203
 	svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1204
       (svg-insert-image svg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1205
       chart)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1206
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1207
 (defun eplot--adjust-horizontal-bar-chart (chart data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1208
   (with-slots ( plots bar-font bar-font-size bar-font-weight margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1209
 		width margin-right xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1210
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1211
     (with-slots ( data-format values) (car plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1212
       (push 'xy data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1213
       ;; Flip the values -- we want the values to be on the X
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1214
       ;; axis instead.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1215
       (setf values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1216
 	    (cl-loop for value in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1217
 		     for i from 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1218
 		     collect (list :value i
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1219
 				   :x (plist-get value :value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1220
 				   :settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1221
 				   (plist-get value :settings))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1222
       (when (eplot--default-p 'margin-left data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1223
 	(setf margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1224
 	      (+ (cl-loop for value in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1225
 			  maximize
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1226
 			  (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1227
 			   (eplot--vs 'label (plist-get value :settings))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1228
 			   bar-font bar-font-size bar-font-weight))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1229
 		 20)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1230
 	      xs (- width margin-left margin-right))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1231
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1232
 (defun eplot--draw-basics (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1233
   (with-slots ( width height 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1234
 		chart-color font font-size font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1235
 		margin-left margin-right margin-top margin-bottom
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1236
 		background-color label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1237
 		xs ys)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1238
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1239
     ;; Add background.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1240
     (eplot--draw-background chart svg 0 0 width height)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1241
     (with-slots ( background-image-file background-image-opacity
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1242
 		  background-image-cover)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1243
 	chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1244
       (when (and background-image-file
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1245
 		 ;; Sanity checks to avoid erroring out later.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1246
 		 (file-exists-p background-image-file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1247
 		 (file-regular-p background-image-file))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1248
 	(apply #'svg-embed svg background-image-file "image/jpeg" nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1249
 	       :opacity background-image-opacity
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1250
 	       :preserveAspectRatio "xMidYMid slice"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1251
 	       (if (memq background-image-cover '(all frame))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1252
 		   `(:x 0 :y 0 :width ,width :height ,height)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1253
 		 `(:x ,margin-left :y ,margin-top :width ,xs :height ,ys)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1254
 	(when (eq background-image-cover 'frame)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1255
 	  (eplot--draw-background chart svg margin-left margin-right xs ys))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1256
     ;; Area between plot and edges.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1257
     (with-slots (surround-color) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1258
       (when surround-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1259
 	(svg-rectangle svg 0 0 width height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1260
 		       :fill surround-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1261
 	(svg-rectangle svg margin-left margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1262
 		       xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1263
 		       :fill background-color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1264
     ;; Border around the entire chart.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1265
     (with-slots (border-width border-color) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1266
       (when (or border-width border-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1267
 	(svg-rectangle svg 0 0 width height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1268
 		       :stroke-width (or border-width 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1269
 		       :fill "none"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1270
 		       :stroke-color (or border-color chart-color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1271
     ;; Frame around the plot.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1272
     (with-slots (frame-width frame-color) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1273
       (when (or frame-width frame-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1274
 	(svg-rectangle svg margin-left margin-top xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1275
 		       :stroke-width (or frame-width 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1276
 		       :fill "none"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1277
 		       :stroke-color (or frame-color chart-color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1278
     ;; Title and legends.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1279
     (with-slots (title title-color) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1280
       (when title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1281
 	(svg-text svg title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1282
 		  :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1283
 		  :text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1284
 		  :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1285
 		  :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1286
 		  :fill title-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1287
 		  :x (+ margin-left (/ (- width margin-left margin-right) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1288
 		  :y (+ 3 (/ margin-top 2)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1289
     (with-slots (x-title) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1290
       (when x-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1291
 	(svg-text svg x-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1292
 		  :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1293
 		  :text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1294
 		  :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1295
 		  :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1296
 		  :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1297
 		  :x (+ margin-left (/ (- width margin-left margin-right) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1298
 		  :y (- height (/ margin-bottom 4)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1299
     (with-slots (y-title) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1300
       (when y-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1301
 	(let ((text-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1302
 	       (eplot--text-height y-title font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1303
 	  (svg-text svg y-title
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1304
 		    :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1305
 		    :text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1306
 		    :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1307
 		    :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1308
 		    :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1309
 		    :transform
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1310
 		    (format "translate(%s,%s) rotate(-90)"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1311
 			    (- (/ margin-left 2) (/ text-height 2) 4)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1312
 			    (+ margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1313
 			       (/ (- height margin-bottom margin-top) 2)))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1314
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1315
 (defun eplot--draw-background (chart svg left top width height)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1316
   (with-slots (background-gradient background-color) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1317
     (let ((gradient (eplot--parse-gradient background-gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1318
 	  id)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1319
       (when gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1320
 	(setq id (format "gradient-%s" (make-temp-name "grad")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1321
 	(eplot--gradient svg id 'linear
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1322
 			 (eplot--stops (eplot--vs 'from gradient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1323
 				       (eplot--vs 'to gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1324
 			 (eplot--vs 'direction gradient)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1325
       (apply #'svg-rectangle svg left top width height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1326
 	     (if gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1327
 		 `(:gradient ,id)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1328
 	       `(:fill ,background-color))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1329
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1330
 (defun eplot--compute-chart-dimensions (chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1331
   (with-slots ( min max plots x-values x-min x-max x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1332
 		print-format font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1333
 		xs
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1334
 		inhibit-compute-x-step x-type x-step-map format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1335
 		x-tick-step x-label-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1336
 		label-font label-font-size x-label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1337
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1338
     (let ((set-min min)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1339
 	  (set-max max))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1340
       (dolist (plot plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1341
 	(with-slots (values data-format) plot
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1342
 	  (let* ((vals (nconc (seq-map (lambda (v) (plist-get v :value)) values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1343
 			      (and (memq 'two-values data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1344
 				   (seq-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1345
 				    (lambda (v) (plist-get v :extra-value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1346
 				    values)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1347
 	    ;; Set the x-values based on the first plot.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1348
 	    (unless x-values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1349
 	      (setq print-format (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1350
 				  ((memq 'year data-format) 'year)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1351
 				  ((memq 'date data-format) 'date)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1352
 				  ((memq 'time data-format) 'time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1353
 				  (t 'number)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1354
 	      (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1355
 	       ((or (memq 'xy data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1356
 		    (memq 'year data-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1357
 		(setq x-values (cl-loop for val in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1358
 					collect (plist-get val :x))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1359
 		      x-min (if (eq format 'horizontal-bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1360
 				0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1361
 			      (seq-min x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1362
 		      x-max (seq-max x-values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1363
 		      x-ticks (eplot--get-ticks x-min x-max xs))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1364
 		(when (memq 'year data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1365
 		  (setq print-format 'literal-year)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1366
 	       ((memq 'date data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1367
 		(setq x-values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1368
 		      (cl-loop for val in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1369
 			       collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1370
 			       (time-to-days
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1371
 				(encode-time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1372
 				 (decoded-time-set-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1373
 				  (iso8601-parse-date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1374
 				   (format "%d" (plist-get val :x)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1375
 		      x-min (seq-min x-values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1376
 		      x-max (seq-max x-values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1377
 		      inhibit-compute-x-step t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1378
 		(let ((xs (eplot--get-date-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1379
 			   x-min x-max xs
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1380
 			   label-font label-font-size x-label-format)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1381
 		  (setq x-ticks (car xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1382
 			print-format (cadr xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1383
 			x-tick-step 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1384
 			x-label-step 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1385
 			x-step-map (nth 2 xs))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1386
 	       ((memq 'time data-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1387
 		(setq x-values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1388
 		      (cl-loop for val in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1389
 			       collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1390
 			       (time-convert
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1391
 				(encode-time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1392
 				 (decoded-time-set-defaults
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1393
 				  (iso8601-parse-time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1394
 				   (format "%06d" (plist-get val :x)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1395
 				'integer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1396
 		      x-min (car x-values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1397
 		      x-max (car (last x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1398
 		      inhibit-compute-x-step t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1399
 		(let ((xs (eplot--get-time-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1400
 			   x-min x-max xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1401
 			   x-label-format)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1402
 		  (setq x-ticks (car xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1403
 			print-format (cadr xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1404
 			x-tick-step 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1405
 			x-label-step 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1406
 			x-step-map (nth 2 xs))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1407
 	       (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1408
 		;; This is a one-dimensional plot -- we don't have X
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1409
 		;; values, really, so we just do zero to (1- (length
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1410
 		;; values)).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1411
 		(setq x-type 'one-dimensional
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1412
 		      x-values (cl-loop for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1413
 					repeat (length values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1414
 					collect i)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1415
 		      x-min (car x-values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1416
 		      x-max (car (last x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1417
 		      x-ticks x-values))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1418
 	    (unless set-min
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1419
 	      (setq min (min (or min 1.0e+INF) (seq-min vals))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1420
 	    (unless set-max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1421
 	      (setq max (max (or max -1.0e+INF) (seq-max vals))))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1422
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1423
 (defun eplot--adjust-chart (chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1424
   (with-slots ( x-tick-step x-label-step y-tick-step y-label-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1425
 		min max ys format inhibit-compute-x-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1426
 		y-ticks xs x-values print-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1427
 		x-label-format label-font label-font-size data
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1428
 		x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1429
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1430
     (setq y-ticks (and max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1431
 		       (eplot--get-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1432
 			min
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1433
 			;; We get 5% more ticks to check whether we
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1434
 			;; should extend max.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1435
 			(if (eplot--default-p 'max data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1436
 			    (* max 1.02)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1437
 			  max)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1438
 			ys)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1439
     (when (eplot--default-p 'max data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1440
       (setq max (max max (car (last y-ticks)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1441
     (if (eq format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1442
 	(setq x-tick-step 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1443
 	      x-label-step 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1444
       (unless inhibit-compute-x-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1445
 	(let ((xt (eplot--compute-x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1446
 		   xs x-ticks print-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1447
 		   x-label-format label-font label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1448
 	  (setq x-tick-step (car xt)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1449
 		x-label-step (cadr xt)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1450
     (when max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1451
       (let ((yt (eplot--compute-y-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1452
 		 ys y-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1453
 		 (eplot--text-height "100" label-font label-font-size))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1454
 	(setq y-tick-step (car yt)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1455
 	      y-label-step (cadr yt))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1456
     ;; If max is less than 2% off from a pleasant number, then
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1457
     ;; increase max.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1458
     (when (eplot--default-p 'max data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1459
       (cl-loop for tick in (reverse y-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1460
 	       when (and (< max tick)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1461
 			 (< (e/ (- tick max) (- max min)) 0.02))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1462
 	       return (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1463
 			(setq max tick)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1464
 			;; Chop off any further ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1465
 			(setcdr (member tick y-ticks) nil))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1466
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1467
     (when y-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1468
       (if (and (eplot--default-p 'min data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1469
 	       (< (car y-ticks) min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1470
 	  (setq min (car y-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1471
 	;; We may be extending the bottom of the chart to get pleasing
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1472
 	;; numbers.  We don't want to be drawing the chart on top of the
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1473
 	;; X axis, because the chart won't be visible there.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1474
 	(when (and nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1475
 		   (<= min (car y-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1476
 		   ;; But not if we start at origo, because that just
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1477
 		   ;; looks confusing.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1478
 		   (not (zerop min)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1479
 	  (setq min (- (car y-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1480
 		       ;; 2% of the value range.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1481
 		       (* 0.02 (- (car (last y-ticks)) (car y-ticks))))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1482
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1483
 (defun eplot--adjust-vertical-x-labels (chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1484
   (with-slots ( x-step-map x-ticks format plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1485
 		print-format x-label-format label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1486
 		label-font-size margin-bottom
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1487
 		bar-font bar-font-size bar-font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1488
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1489
     ;; Make X ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1490
     (let ((width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1491
 	   (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1492
 	    for xv in (or x-step-map x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1493
 	    for x = (if (consp xv) (car xv) xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1494
 	    for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1495
 	    for value = (and (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1496
 			     (elt (slot-value (car plots) 'values) i))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1497
 	    for label = (if (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1498
 			    (eplot--vs 'label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1499
 				       (plist-get value :settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1500
 				       ;; When we're doing bar charts, we
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1501
 				       ;; want default labeling to start with
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1502
 				       ;; 1 and not zero.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1503
 				       (format "%s" (1+ x)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1504
 			  (eplot--format-value x print-format x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1505
 	    maximize (if (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1506
 			 (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1507
 			  label bar-font bar-font-size bar-font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1508
 		       (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1509
 			label label-font label-font-size)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1510
       ;; Ensure that we have enough room to display the X labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1511
       ;; (unless overridden).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1512
       (with-slots ( height margin-top ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1513
 		    y-ticks y-tick-step y-label-step min max)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1514
 	  chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1515
 	(setq margin-bottom (max margin-bottom (+ width 40))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1516
 	      ys (- height margin-top margin-bottom))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1517
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1518
 (defun eplot--compute-x-labels (chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1519
   (with-slots ( x-step-map x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1520
 		format plots print-format x-label-format x-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1521
 		x-tick-step x-label-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1522
 		x-label-orientation margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1523
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1524
     ;; Make X ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1525
     (setf x-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1526
 	  (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1527
 	   for xv in (or x-step-map x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1528
 	   for x = (if (consp xv) (car xv) xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1529
 	   for do-tick = (if (consp xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1530
 			     (nth 1 xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1531
 			   (zerop (e% x x-tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1532
 	   for do-label = (if (consp xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1533
 			      (nth 2 xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1534
 			    (zerop (e% x x-label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1535
 	   for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1536
 	   for value = (and (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1537
 			    (elt (slot-value (car plots) 'values) i))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1538
 	   collect (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1539
 		    (if (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1540
 			(eplot--vs 'label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1541
 				   (plist-get value :settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1542
 				   ;; When we're doing bar charts, we
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1543
 				   ;; want default labeling to start with
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1544
 				   ;; 1 and not zero.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1545
 				   (format "%s" (1+ x)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1546
 		      (eplot--format-value x print-format x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1547
 		    do-tick
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1548
 		    do-label)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1549
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1550
 (defun eplot--draw-x-ticks (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1551
   (with-slots ( x-step-map x-ticks format layout print-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1552
 		margin-left margin-right margin-top margin-bottom
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1553
 		x-min x-max xs
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1554
 		width height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1555
 		axes-color label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1556
 		grid grid-opacity grid-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1557
 		font x-tick-step x-label-step x-label-format x-label-orientation
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1558
 		label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1559
 		plots x-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1560
 		bar-font bar-font-size bar-font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1561
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1562
     (let ((font label-font)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1563
 	  (font-size label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1564
 	  (font-weight 'normal))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1565
       (when (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1566
 	(setq font bar-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1567
 	      font-size bar-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1568
 	      font-weight bar-font-weight))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1569
       ;; Make X ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1570
       (cl-loop with label-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1571
 	       for xv in (or x-step-map x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1572
 	       for x = (if (consp xv) (car xv) xv)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1573
 	       for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1574
 	       for (label do-tick do-label) in x-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1575
 	       for stride = (eplot--stride chart x-ticks)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1576
 	       for px = (if (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1577
 			    (+ margin-left (* x stride) (/ stride 2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1578
 			       (/ (* stride 0.1) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1579
 			  (+ margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1580
 			     (* (/ (- (* 1.0 x) x-min) (- x-max x-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1581
 				xs)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1582
 	       ;; We might have one extra stride outside the area -- don't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1583
 	       ;; draw it.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1584
 	       when (<= px (- width margin-right))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1585
 	       do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1586
 	       (when do-tick
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1587
 		 ;; Draw little tick.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1588
 		 (unless (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1589
 		   (svg-line svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1590
 			     px (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1591
 			     px (+ (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1592
 				   (if do-label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1593
 				       4
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1594
 				     2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1595
 			     :stroke axes-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1596
 		 (when (or (eq grid 'xy) (eq grid 'x))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1597
 		   (svg-line svg px margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1598
 			     px (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1599
 			     :opacity grid-opacity
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1600
 			     :stroke grid-color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1601
 	       (when (and do-label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1602
 			  ;; We want to skip marking the first X value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1603
 			  ;; unless we're a bar chart or we're a one
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1604
 			  ;; dimensional chart.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1605
 			  (or (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1606
 			      t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1607
 			      (not (= x-min (car x-values)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1608
 			      (eq x-type 'one-dimensional)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1609
 			      (and (not (zerop x)) (not (zerop i)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1610
 		 (if (eq x-label-orientation 'vertical)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1611
 		     (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1612
 		       (unless label-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1613
 			 ;; The X position we're putting the label at is
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1614
 			 ;; based on the bottom of the lower-case
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1615
 			 ;; characters.  So we want to ignore descenders
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1616
 			 ;; etc, so we use "xx" to determine the height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1617
 			 ;; to be able to center the text.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1618
 			 (setq label-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1619
 			       (eplot--text-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1620
 				;; If the labels are numerical, we need
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1621
 				;; to center them using the height of
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1622
 				;; numbers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1623
 				(if (string-match "^[0-9]+$" label)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1624
 				    "10"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1625
 				  ;; Otherwise center them on the baseline.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1626
 				  "xx")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1627
 				font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1628
 		       (svg-text svg label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1629
 				 :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1630
 				 :text-anchor "end"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1631
 				 :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1632
 				 :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1633
 				 :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1634
 				 :transform
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1635
 				 (format "translate(%s,%s) rotate(-90)"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1636
 					 (+ px (/ label-height 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1637
 					 (- height margin-bottom -10))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1638
 		   (svg-text svg label
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1639
 			     :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1640
 			     :text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1641
 			     :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1642
 			     :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1643
 			     :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1644
 			     :x px
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1645
 			     :y (+ (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1646
 				   font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1647
 				   (if (equal format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1648
 				       (if (equal layout 'compact) 3 5)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1649
 				     2)))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1650
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1651
 (defun eplot--stride (chart values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1652
   (with-slots (xs x-type format) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1653
     (if (eq x-type 'one-dimensional)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1654
 	(e/ xs
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1655
 	    ;; Fenceposting bar-chart vs everything else.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1656
 	    (if (eq format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1657
 		(length values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1658
 	      (1- (length values))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1659
       (e/ xs (length values)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1660
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1661
 (defun eplot--default-p (slot data)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1662
   "Return non-nil if SLOT is at the default value."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1663
   (and (not (assq slot eplot--user-defaults))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1664
        (not (assq slot data))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1665
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1666
 (defun eplot--compute-y-labels (chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1667
   (with-slots ( y-ticks y-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1668
 		width height min max xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1669
 		margin-top margin-bottom margin-left margin-right
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1670
 		y-tick-step y-label-step y-label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1671
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1672
     ;; First collect all the labels we're thinking about outputting.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1673
     (setq y-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1674
 	  (cl-loop for y in y-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1675
 		   for py = (- (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1676
 			       (* (/ (- (* 1.0 y) min) (- max min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1677
 				  ys))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1678
 		   when (and (<= margin-top py (- height margin-bottom))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1679
 			     (zerop (e% y y-tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1680
 			     (zerop (e% y y-label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1681
 		   collect (eplot--format-y
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1682
 			    y (- (cadr y-ticks) (car y-ticks)) nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1683
 			    y-label-format)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1684
     ;; Check the labels to see whether we have too many digits for
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1685
     ;; what we're actually going to display.  Man, this is a lot of
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1686
     ;; back-and-forth and should be rewritten to be less insanely
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1687
     ;; inefficient.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1688
     (when (= (seq-count (lambda (label)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1689
 			  (string-match "\\." label))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1690
 			y-labels)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1691
 	     (length y-labels))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1692
       (setq y-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1693
 	    (cl-loop with max = (cl-loop for label in y-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1694
 					 maximize (eplot--decimal-digits
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1695
 						   (string-to-number label)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1696
 		     for label in y-labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1697
 		     collect (format (if (zerop max)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1698
 					 "%d"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1699
 				       (format "%%.%df" max))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1700
 				     (string-to-number label)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1701
     (setq y-labels (cl-coerce y-labels 'vector))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1702
     ;; Ensure that we have enough room to display the Y labels
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1703
     ;; (unless overridden).
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1704
     (when (eplot--default-p 'margin-left (slot-value chart 'data))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1705
       (with-slots (label-font label-font-size) chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1706
 	(setq margin-left (max margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1707
 			       (+ (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1708
 				   (elt y-labels (1- (length y-labels)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1709
 				   label-font label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1710
 				  10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1711
 	      xs (- width margin-left margin-right))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1712
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1713
 (defun eplot--draw-y-ticks (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1714
   (with-slots ( y-ticks y-labels y-tick-step y-label-step label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1715
 		label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1716
 		width height min max ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1717
 		margin-top margin-bottom margin-left margin-right
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1718
 		axes-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1719
 		grid grid-opacity grid-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1720
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1721
     ;; Make Y ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1722
     (cl-loop with lnum = 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1723
 	     with text-height = (eplot--text-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1724
 				 "012" label-font label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1725
 	     for y in y-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1726
 	     for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1727
 	     for py = (- (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1728
 			 (* (/ (- (* 1.0 y) min) (- max min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1729
 			    ys))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1730
 	     do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1731
 	     (when (and (<= margin-top py (- height margin-bottom))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1732
 			(zerop (e% y y-tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1733
 	       (svg-line svg margin-left py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1734
 			 (- margin-left 3) py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1735
 			 :stroke-color axes-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1736
 	       (when (or (eq grid 'xy) (eq grid 'y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1737
 		 (svg-line svg margin-left py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1738
 			   (- width margin-right) py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1739
 			   :opacity grid-opacity
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1740
 			   :stroke-color grid-color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1741
 	       (when (zerop (e% y y-label-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1742
 		 (svg-text svg (elt y-labels lnum)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1743
 			   :font-family label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1744
 			   :text-anchor "end"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1745
 			   :font-size label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1746
 			   :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1747
 			   :x (- margin-left 6)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1748
 			   :y (+ py (/ text-height 2) -1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1749
 		 (cl-incf lnum))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1750
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1751
 (defun eplot--text-width (text font font-size &optional font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1752
   (string-pixel-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1753
    (propertize text 'face
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1754
 	       (list :font (font-spec :family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1755
 				      :weight (or font-weight 'normal)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1756
 				      :size font-size)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1757
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1758
 (defvar eplot--text-size-cache (make-hash-table :test #'equal))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1759
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1760
 (defun eplot--text-height (text font font-size &optional font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1761
   (cdr (eplot--text-size text font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1762
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1763
 (defun eplot--text-size (text font font-size font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1764
   (let ((key (list text font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1765
     (or (gethash key eplot--text-size-cache)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1766
 	(let ((size (eplot--text-size-1 text font font-size font-weight)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1767
 	  (setf (gethash key eplot--text-size-cache) size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1768
 	  size))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1769
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1770
 (defun eplot--text-size-1 (text font font-size font-weight)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1771
   (if (not (executable-find "convert"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1772
       ;; This "default" text size is kinda bogus.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1773
       (cons (* (length text) font-size) font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1774
     (let* ((size (* font-size 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1775
 	   (svg (svg-create size size))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1776
 	   text-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1777
       (svg-rectangle svg 0 0 size size :fill "black")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1778
       (svg-text svg text
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1779
 		:font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1780
 		:text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1781
 		:font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1782
 		:font-weight (or font-weight 'normal)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1783
 		:fill "white"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1784
 		:x (/ size 2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1785
 		:y (/ size 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1786
       (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1787
 	(set-buffer-multibyte nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1788
 	(svg-print svg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1789
 	(let* ((file (concat (make-temp-name "/tmp/eplot") ".svg"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1790
 	       (png (file-name-with-extension file ".png")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1791
 	  (unwind-protect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1792
 	      (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1793
 		(write-region (point-min) (point-max) file nil 'silent)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1794
 		;; rsvg-convert is 5x faster than convert when doing SVG, so
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1795
 		;; if we have it, we use it.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1796
 		(when (executable-find "rsvg-convert")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1797
 		  (unwind-protect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1798
 		      (call-process "rsvg-convert" nil nil nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1799
 				    (format "--output=%s" png) file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1800
 		    (when (file-exists-p png)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1801
 		      (delete-file file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1802
 		      (setq file png))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1803
 		(erase-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1804
 		(when (zerop (call-process "convert" nil t nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1805
 					   "-trim" "+repage" file "info:-"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1806
 		  (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1807
 		  (when (re-search-forward " \\([0-9]+\\)x\\([0-9]+\\)" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1808
 		    (setq text-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1809
 			  (cons (string-to-number (match-string 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1810
 				(string-to-number (match-string 2)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1811
 	    (when (file-exists-p file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1812
 	      (delete-file file)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1813
       (or text-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1814
 	  ;; This "default" text size is kinda bogus.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1815
 	  (cons (* (length text) font-size) font-size)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1816
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1817
 (defun eplot--draw-legend (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1818
   (with-slots ( legend plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1819
 		margin-left margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1820
 		font font-size font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1821
 		background-color axes-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1822
 		legend-color legend-background-color legend-border-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1823
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1824
     (when (eq legend 'true)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1825
       (when-let ((names
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1826
 		  (cl-loop for plot in plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1827
 			   for name = (slot-value plot 'name)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1828
 			   when name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1829
 			   collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1830
 			   (cons name (slot-value plot 'color)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1831
 	(svg-rectangle svg (+ margin-left 20) (+ margin-top 20)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1832
 		       (format "%dex"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1833
 			       (+ 2
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1834
 				  (seq-max (mapcar (lambda (name)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1835
 						     (length (car name)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1836
 						   names))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1837
 		       (* font-size (+ (length names) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1838
 		       :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1839
 		       :fill-color legend-background-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1840
 		       :stroke-color legend-border-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1841
 	(cl-loop for name in names
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1842
 		 for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1843
 		 do (svg-text svg (car name)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1844
 			      :font-family font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1845
 			      :text-anchor "front"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1846
 			      :font-size font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1847
 			      :font-weight font-weight
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1848
 			      :fill (or (cdr name) legend-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1849
 			      :x (+ margin-left 25)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1850
 			      :y (+ margin-top 40 (* i font-size))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1851
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1852
 (defun eplot--format-y (y spacing whole format-string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1853
   (format (or format-string "%s")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1854
 	  (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1855
 	   ((or (= (round (* spacing 100)) 10) (= (round (* spacing 100)) 20))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1856
 	    (format "%.1f" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1857
 	   ((< spacing 0.01)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1858
 	    (format "%.3f" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1859
 	   ((< spacing 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1860
 	    (format "%.2f" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1861
 	   ((and (< spacing 1) (not (zerop (mod (* spacing 10) 1))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1862
 	    (format "%.1f" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1863
 	   ((zerop (% spacing 1000000000))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1864
 	    (format "%dG" (/ y 1000000000)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1865
 	   ((zerop (% spacing 1000000))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1866
 	    (format "%dM" (/ y 1000000)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1867
 	   ((zerop (% spacing 1000))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1868
 	    (format "%dk" (/ y 1000)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1869
 	   ((>= spacing 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1870
 	    (format "%s" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1871
 	   ((not whole)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1872
 	    (format "%.1f" y))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1873
 	   (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1874
 	    (format "%s" y)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1875
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1876
 (defun eplot--format-value (value print-format label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1877
   (replace-regexp-in-string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1878
    ;; Texts in SVG collapse multiple spaces into one.  So do it here,
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1879
    ;; too, so that width calculations are correct.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1880
    " +" " "
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1881
    (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1882
     ((eq print-format 'date)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1883
      (format-time-string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1884
       (or label-format "%Y-%m-%d") (eplot--days-to-time value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1885
     ((eq print-format 'year)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1886
      (format-time-string (or label-format "%Y") (eplot--days-to-time value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1887
     ((eq print-format 'time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1888
      (format-time-string (or label-format "%H:%M:%S") value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1889
     ((eq print-format 'minute)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1890
      (format-time-string (or label-format "%H:%M") value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1891
     ((eq print-format 'hour)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1892
      (format-time-string (or label-format "%H") value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1893
     (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1894
      (format (or label-format "%s") value)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1895
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1896
 (defun eplot--compute-x-ticks (xs x-values print-format x-label-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1897
 				  label-font label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1898
   (let* ((min (seq-min x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1899
 	 (max (seq-max x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1900
 	 (count (length x-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1901
 	 (max-print (eplot--format-value max print-format x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1902
 	 ;; We want each label to be spaced at least as long apart as
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1903
 	 ;; the length of the longest label, with room for two blanks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1904
 	 ;; in between.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1905
 	 (min-spacing (* 1.2 (eplot--text-width max-print label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1906
 						label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1907
 	 (digits (eplot--decimal-digits (- (cadr x-values) (car x-values))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1908
 	 (every (e/ 1 (expt 10 digits))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1909
     (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1910
      ;; We have room for every X value.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1911
      ((< (* count min-spacing) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1912
       (list every every))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1913
      ;; We have to prune X labels, but not grid lines.  (We shouldn't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1914
      ;; have a grid line more than every 10 pixels.)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1915
      ((< (* count 10) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1916
       (list every
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1917
 	    (let ((label-step every))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1918
 	      (while (> (/ (- max min) label-step) (/ xs min-spacing))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1919
 		(setq label-step (eplot--next-weed label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1920
 	      label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1921
      ;; We have to reduce both grid lines and labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1922
      (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1923
       (let ((tick-step every))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1924
 	(while (> (/ (- max min) tick-step) (/ xs 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1925
 	  (setq tick-step (eplot--next-weed tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1926
 	(list tick-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1927
 	      (let ((label-step tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1928
 		(while (> (/ (- max min) label-step) (/ xs min-spacing))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1929
 		  (setq label-step (eplot--next-weed label-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1930
 		  (while (not (zerop (% label-step tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1931
 		    (setq label-step (eplot--next-weed label-step))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1932
 		label-step)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1933
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1934
 (defun eplot--compute-y-ticks (ys y-values text-height)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1935
   (let* ((min (car y-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1936
 	 (max (car (last y-values)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1937
 	 (count (length y-values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1938
 	 ;; We want each label to be spaced at least as long apart as
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1939
 	 ;; the height of the label.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1940
 	 (min-spacing (+ text-height 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1941
 	 (digits (eplot--decimal-digits (- (cadr y-values) (car y-values))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1942
 	 (every (e/ 1 (expt 10 digits))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1943
     (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1944
      ;; We have room for every X value.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1945
      ((< (* count min-spacing) ys)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1946
       (list every every))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1947
      ;; We have to prune Y labels, but not grid lines.  (We shouldn't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1948
      ;; have a grid line more than every 10 pixels.)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1949
      ((< (* count 10) ys)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1950
       (list every
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1951
 	    (let ((label-step every))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1952
 	      (while (> (/ (- max min) label-step) (/ ys min-spacing))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1953
 		(setq label-step (eplot--next-weed label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1954
 	      label-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1955
      ;; We have to reduce both grid lines and labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1956
      (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1957
       (let ((tick-step 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1958
 	(while (> (/ count tick-step) (/ ys 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1959
 	  (setq tick-step (eplot--next-weed tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1960
 	(list tick-step
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1961
 	      (let ((label-step tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1962
 		(while (> (/ count label-step) (/ ys min-spacing))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1963
 		  (setq label-step (eplot--next-weed label-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1964
 		  (while (not (zerop (% label-step tick-step)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1965
 		    (setq label-step (eplot--next-weed label-step))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1966
 		label-step)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1967
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1968
 (defvar eplot--pleasing-numbers '(1 2 5 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1969
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1970
 (defun eplot--next-weed (weed)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1971
   (let (digits series)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1972
     (if (>= weed 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1973
 	(setq digits (truncate (log weed 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1974
 	      series (/ weed (expt 10 digits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1975
       (setq digits (eplot--decimal-digits weed)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1976
 	    series (truncate (* weed (expt 10 digits)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1977
     (let ((next (cadr (memq series eplot--pleasing-numbers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1978
       (unless next
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1979
 	(error "Invalid weed: %s" weed))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1980
       (if (>= weed 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1981
 	  (* next (expt 10 digits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1982
 	(e/ next (expt 10 digits))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1983
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1984
 (defun eplot--parse-gradient (string)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1985
   (when string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1986
     (let ((bits (split-string string)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1987
       (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1988
        (cons 'from (nth 0 bits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1989
        (cons 'to (nth 1 bits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1990
        (cons 'direction (intern (or (nth 2 bits) "top-down")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1991
        (cons 'position (intern (or (nth 3 bits) "below")))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1992
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1993
 (defun eplot--smooth (values algo xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1994
   (if (not algo)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1995
       values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1996
     (let* ((vals (cl-coerce values 'vector))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1997
 	   (max (1- (length vals)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1998
 	   (period (* 4 (ceiling (/ max xs)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1999
       (cl-case algo
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2000
 	(moving-average
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2001
 	 (cl-loop for i from 0 upto max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2002
 		  collect (e/ (cl-loop for ii from 0 upto (1- period)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2003
 				       sum (elt vals (min (+ i ii) max)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2004
 			      period)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2005
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2006
 (defun eplot--vary-color (color n)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2007
   (let ((colors ["#e6194b" "#3cb44b" "#ffe119" "#4363d8" "#f58231" "#911eb4"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2008
 		 "#46f0f0" "#f032e6" "#bcf60c" "#fabebe" "#008080" "#e6beff"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2009
 		 "#9a6324" "#fffac8" "#800000" "#aaffc3" "#808000" "#ffd8b1"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2010
 		 "#000075" "#808080" "#ffffff" "#000000"]))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2011
     (unless (equal color "vary")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2012
       (setq colors
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2013
 	    (if (string-search " " color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2014
 		(split-string color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2015
 	      (list color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2016
     (elt colors (mod n (length colors)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2017
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2018
 (defun eplot--pv (plot slot &optional default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2019
   (let ((user (cdr (assq slot eplot--user-defaults))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2020
     (when (and (stringp user) (zerop (length user)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2021
       (setq user nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2022
     (or user (slot-value plot slot) default)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2023
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2024
 (defun eplot--draw-plots (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2025
   (if (eq (slot-value chart 'format) 'horizontal-bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2026
       (eplot--draw-horizontal-bar-chart svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2027
     (eplot--draw-normal-plots svg chart)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2028
     
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2029
 (defun eplot--draw-normal-plots (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2030
   (with-slots ( plots chart-color height format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2031
 		margin-bottom margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2032
 		min max xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2033
 		margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2034
 		x-values x-min x-max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2035
 		label-font label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2036
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2037
     ;; Draw all the plots.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2038
     (cl-loop for plot in (reverse plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2039
 	     for plot-number from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2040
 	     for values = (slot-value plot 'values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2041
 	     for stride = (eplot--stride chart values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2042
 	     for vals = (eplot--smooth
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2043
 			 (seq-map (lambda (v) (plist-get v :value)) values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2044
 			 (slot-value plot 'smoothing)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2045
 			 xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2046
 	     for polygon = nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2047
 	     for gradient = (eplot--parse-gradient (eplot--pv plot 'gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2048
 	     for lpy = nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2049
 	     for lpx = nil
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2050
 	     for style = (if (eq format 'bar-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2051
 			     'bar
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2052
 			   (slot-value plot 'style))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2053
 	     for bar-gap = (* stride 0.1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2054
 	     for clip-id = (format "url(#clip-%d)" plot-number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2055
 	     do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2056
 	     (svg--append
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2057
 	      svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2058
 	      (dom-node 'clipPath
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2059
 			`((id . ,(format "clip-%d" plot-number)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2060
 			(dom-node 'rect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2061
 				  `((x . ,margin-left)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2062
 				    (y . , margin-top)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2063
 				    (width . ,xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2064
 				    (height . ,ys)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2065
 	     (unless gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2066
 	       (when-let ((fill (slot-value plot 'fill-color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2067
 		 (setq gradient `((from . ,fill) (to . ,fill)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2068
 				  (direction . top-down) (position . below)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2069
 	     (when gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2070
 	       (if (eq (eplot--vs 'position gradient) 'above)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2071
 		   (push (cons margin-left margin-top) polygon)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2072
 		 (push (cons margin-left (- height margin-bottom)) polygon)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2073
 	     (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2074
 	      for val in vals
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2075
 	      for value in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2076
 	      for x in x-values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2077
 	      for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2078
 	      for settings = (plist-get value :settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2079
 	      for color = (eplot--vary-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2080
 			   (eplot--vs 'color settings (slot-value plot 'color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2081
 			   i)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2082
 	      for py = (- (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2083
 			  (* (/ (- (* 1.0 val) min) (- max min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2084
 			     ys))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2085
 	      for px = (if (eq style 'bar)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2086
 			   (+ margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2087
 			      (* (e/ (- x x-min) (- x-max x-min -1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2088
 				 xs))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2089
 			 (+ margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2090
 			    (* (e/ (- x x-min) (- x-max x-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2091
 			       xs)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2092
 	      do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2093
 	      ;; Some data points may have texts.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2094
 	      (when-let ((text (eplot--vs 'text settings)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2095
 		(svg-text svg text
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2096
 			  :font-family label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2097
 			  :text-anchor "middle"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2098
 			  :font-size label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2099
 			  :font-weight 'normal
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2100
 			  :fill color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2101
 			  :x px 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2102
 			  :y (- py (eplot--text-height
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2103
 				    text label-font label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2104
 				-5)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2105
 	      ;; You may mark certain points.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2106
 	      (when-let ((mark (eplot--vy 'mark settings)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2107
 		(cl-case mark
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2108
 		  (cross
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2109
 		   (let ((s (eplot--element-size val plot settings 3)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2110
 		     (svg-line svg (- px s) (- py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2111
 			       (+ px s) (+ py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2112
 			       :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2113
 			       :stroke color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2114
 		     (svg-line svg (+ px s) (- py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2115
 			       (- px s) (+ py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2116
 			       :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2117
 			       :stroke color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2118
 		  (otherwise
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2119
 		   (svg-circle svg px py 3
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2120
 			       :fill color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2121
 	      (cl-case style
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2122
 		(bar
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2123
 		 (if (not gradient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2124
 		     (svg-rectangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2125
 		      svg (+ px bar-gap) py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2126
 		      (- stride bar-gap) (- height margin-bottom py)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2127
 		      :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2128
 		      :fill color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2129
 		   (let ((id (format "gradient-%s" (make-temp-name "grad"))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2130
 		     (eplot--gradient svg id 'linear
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2131
 				      (eplot--stops (eplot--vs 'from gradient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2132
 						    (eplot--vs 'to gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2133
 				      (eplot--vs 'direction gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2134
 		     (svg-rectangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2135
 		      svg (+ px bar-gap) py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2136
 		      (- stride bar-gap) (- height margin-bottom py)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2137
 		      :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2138
 		      :gradient id))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2139
 		(impulse
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2140
 		 (let ((width (eplot--element-size val plot settings 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2141
 		   (if (= width 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2142
 		       (svg-line svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2143
 				 px py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2144
 				 px (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2145
 				 :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2146
 				 :stroke color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2147
 		     (svg-rectangle svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2148
 				    (- px (e/ width 2)) py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2149
 				    width (- height py margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2150
 				    :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2151
 				    :fill color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2152
 		(point
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2153
 		 (svg-line svg px py (1+ px) (1+ py)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2154
 			   :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2155
 			   :stroke color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2156
 		(line
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2157
 		 ;; If we're doing a gradient, we're just collecting
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2158
 		 ;; points and will draw the polygon later.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2159
 		 (if gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2160
 		     (push (cons px py) polygon)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2161
 		   (when lpx
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2162
 		     (svg-line svg lpx lpy px py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2163
 			       :stroke-width (eplot--pv plot 'size 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2164
 			       :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2165
 			       :stroke color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2166
 		(curve
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2167
 		 (push (cons px py) polygon))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2168
 		(square
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2169
 		 (if gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2170
 		     (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2171
 		       (when lpx
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2172
 			 (push (cons lpx py) polygon))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2173
 		       (push (cons px py) polygon))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2174
 		   (when lpx
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2175
 		     (svg-line svg lpx lpy px lpy
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2176
 			       :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2177
 			       :stroke color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2178
 		     (svg-line svg px lpy px py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2179
 			       :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2180
 			       :stroke color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2181
 		(circle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2182
 		 (svg-circle svg px py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2183
 			     (eplot--element-size val plot settings 3)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2184
 			     :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2185
 			     :stroke color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2186
 			     :fill (eplot--vary-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2187
 				    (eplot--vs
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2188
 				     'fill-color settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2189
 				     (or (slot-value plot 'fill-color) "none"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2190
 				    i)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2191
 		(cross
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2192
 		 (let ((s (eplot--element-size val plot settings 3)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2193
 		   (svg-line svg (- px s) (- py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2194
 			     (+ px s) (+ py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2195
 			     :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2196
 			     :stroke color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2197
 		   (svg-line svg (+ px s) (- py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2198
 			     (- px s) (+ py s)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2199
 			     :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2200
 			     :stroke color)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2201
 		(triangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2202
 		 (let ((s (eplot--element-size val plot settings 5)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2203
 		   (svg-polygon svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2204
 				(list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2205
 				 (cons (- px (e/ s 2)) (+ py (e/ s 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2206
 				 (cons px (- py (e/ s 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2207
 				 (cons (+ px (e/ s 2)) (+ py (e/ s 2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2208
 				:clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2209
 				:stroke color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2210
 				:fill-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2211
 				(or (slot-value plot 'fill-color) "none"))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2212
 		(rectangle
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2213
 		 (let ((s (eplot--element-size val plot settings 3)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2214
 		   (svg-rectangle svg (- px (e/ s 2)) (- py (e/ s 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2215
 				  s s
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2216
 				  :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2217
 				  :stroke color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2218
 				  :fill-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2219
 				  (or (slot-value plot 'fill-color) "none")))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2220
 	      (setq lpy py
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2221
 		    lpx px))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2222
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2223
 	     ;; We're doing a gradient of some kind (or a curve), so
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2224
 	     ;; draw it now when we've collected the polygon.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2225
 	     (when polygon
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2226
 	       ;; We have a "between" chart, so collect the data points
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2227
 	       ;; from the "extra" values, too.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2228
 	       (when (memq 'two-values (slot-value plot 'data-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2229
 		 (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2230
 		  for val in (nreverse
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2231
 			      (seq-map (lambda (v) (plist-get v :extra-value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2232
 				       values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2233
 		  for x from (1- (length vals)) downto 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2234
 		  for py = (- (- height margin-bottom)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2235
 			      (* (/ (- (* 1.0 val) min) (- max min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2236
 				 ys))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2237
 		  for px = (+ margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2238
 			      (* (e/ (- x x-min) (- x-max x-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2239
 				 xs))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2240
 		  do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2241
 		  (cl-case style
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2242
 		    (line
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2243
 		     (push (cons px py) polygon))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2244
 		    (square
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2245
 		     (when lpx
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2246
 		       (push (cons lpx py) polygon))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2247
 		     (push (cons px py) polygon)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2248
 		  (setq lpx px lpy py)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2249
 	       (when gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2250
 		 (if (eq (eplot--vs 'position gradient) 'above)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2251
 		     (push (cons lpx margin-top) polygon)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2252
 		   (push (cons lpx (- height margin-bottom)) polygon)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2253
 	       (let ((id (format "gradient-%d" plot-number)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2254
 		 (when gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2255
 		   (eplot--gradient svg id 'linear
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2256
 				    (eplot--stops (eplot--vs 'from gradient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2257
 						  (eplot--vs 'to gradient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2258
 				    (eplot--vs 'direction gradient)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2259
 		 (if (eq style 'curve)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2260
 		     (apply #'svg-path svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2261
 			    (nconc
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2262
 			     (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2263
 			      with points = (cl-coerce
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2264
 					     (nreverse polygon) 'vector)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2265
 			      for i from 0 upto (1- (length points))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2266
 			      collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2267
 			      (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2268
 			       ((zerop i)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2269
 				`(moveto ((,(car (elt points 0)) .
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2270
 					   ,(cdr (elt points 0))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2271
 			       (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2272
 				`(curveto
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2273
 				  (,(eplot--bezier
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2274
 				     (eplot--pv plot 'bezier-factor)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2275
 				     i points))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2276
 			     (and gradient '((closepath))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2277
 			    `( :clip-path ,clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2278
 			       :stroke-width ,(eplot--pv plot 'size 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2279
 			       :stroke ,(slot-value plot 'color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2280
 			       ,@(if gradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2281
 				     `(:gradient ,id)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2282
 				   `(:fill "none"))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2283
 		   (svg-polygon
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2284
 		    svg (nreverse polygon)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2285
 		    :clip-path clip-id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2286
 		    :gradient id
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2287
 		    :stroke (slot-value plot 'fill-border-color))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2288
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2289
 (defun eplot--element-size (value plot settings default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2290
   (eplot--vn 'size settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2291
 	     (if (slot-value plot 'size-factor)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2292
 		 (* value (slot-value plot 'size-factor))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2293
 	       (or (slot-value plot 'size) default))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2294
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2295
 (defun eplot--draw-horizontal-bar-chart (svg chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2296
   (with-slots ( plots chart-color height format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2297
 		margin-bottom margin-left
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2298
 		min max xs ys
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2299
 		margin-top
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2300
 		x-values x-min x-max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2301
 		label-font label-font-size label-color)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2302
       chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2303
     (cl-loop with plot = (car plots)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2304
 	     with values = (slot-value plot 'values)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2305
 	     with stride = (e/ ys (length values))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2306
 	     with label-height = (eplot--text-height "xx" label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2307
 						     label-font-size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2308
 	     with bar-gap = (* stride 0.1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2309
 	     for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2310
 	     for value in values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2311
 	     for settings = (plist-get value :settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2312
 	     for py = (+ margin-top (* i stride))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2313
 	     for px = (* (e/ (plist-get value :x) x-max) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2314
 	     for color = (eplot--vary-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2315
 			  (eplot--vs 'color settings (slot-value plot 'color))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2316
 			  i)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2317
 	     do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2318
 	     (svg-text svg (eplot--vs 'label settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2319
 		       :font-family label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2320
 		       :text-anchor "left"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2321
 		       :font-size label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2322
 		       :font-weight 'normal
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2323
 		       :fill label-color
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2324
 		       :x 5
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2325
 		       :y (+ py label-height (/ (- stride label-height) 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2326
 	     (svg-rectangle svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2327
 			    margin-left (+ py (e/ bar-gap 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2328
 			    px (- stride bar-gap)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2329
 			    :fill color))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2330
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2331
 (defun eplot--stops (from to)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2332
   (append `((0 . ,from))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2333
 	  (cl-loop for (pct col) on (split-string to "-") by #'cddr
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2334
 		   collect (if col
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2335
 			       (cons (string-to-number pct) col)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2336
 			     (cons 100 pct)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2337
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2338
 (defun eplot--gradient (svg id type stops &optional direction)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2339
   "Add a gradient with ID to SVG.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2340
 TYPE is `linear' or `radial'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2341
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2342
 STOPS is a list of percentage/color pairs.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2343
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2344
 DIRECTION is one of `top-down', `bottom-up', `left-right' or `right-left'.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2345
 nil means `top-down'."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2346
   (svg--def
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2347
    svg
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2348
    (apply
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2349
     #'dom-node
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2350
     (if (eq type 'linear)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2351
 	'linearGradient
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2352
       'radialGradient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2353
     `((id . ,id)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2354
       (x1 . ,(if (eq direction 'left-right) 1 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2355
       (x2 . ,(if (eq direction 'right-left) 1 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2356
       (y1 . ,(if (eq direction 'bottom-up) 1 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2357
       (y2 . ,(if (eq direction 'top-down) 1 0)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2358
     (mapcar
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2359
      (lambda (stop)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2360
        (dom-node 'stop `((offset . ,(format "%s%%" (car stop)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2361
 			 (stop-color . ,(cdr stop)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2362
      stops))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2363
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2364
 (defun e% (num1 num2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2365
   (let ((factor (max (expt 10 (eplot--decimal-digits num1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2366
 		     (expt 10 (eplot--decimal-digits num2)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2367
     (% (truncate (* num1 factor)) (truncate (* num2 factor)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2368
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2369
 (defun eplot--decimal-digits (number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2370
   (- (length (replace-regexp-in-string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2371
 	      "0+\\'" ""
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2372
 	      (format "%.10f" (- number (truncate number)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2373
      2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2374
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2375
 (defun e/ (&rest numbers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2376
   (if (cl-every #'integerp numbers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2377
       (let ((int (apply #'/ numbers))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2378
 	    (float (apply #'/ (* 1.0 (car numbers)) (cdr numbers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2379
 	(if (= int float)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2380
 	    int
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2381
 	  float))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2382
     (apply #'/ numbers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2383
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2384
 (defun eplot--get-ticks (min max height &optional whole)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2385
   (let* ((diff (abs (- min max)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2386
 	 (even (eplot--pleasing-numbers (* (e/ diff height) 10)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2387
 	 (factor (max (expt 10 (eplot--decimal-digits even))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2388
 		      (expt 10 (eplot--decimal-digits diff))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2389
 	 (fmin (truncate (* min factor)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2390
 	 (feven (truncate (* factor even)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2391
 	 start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2392
     (when whole
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2393
       (setq even 1
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2394
 	    feven factor))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2395
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2396
     (setq start
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2397
 	  (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2398
 	   ((< min 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2399
 	    (+ (floor fmin)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2400
 	       feven
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2401
 	       (- (% (floor fmin) feven))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2402
 	       (- feven)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2403
 	   (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2404
 	    (- fmin (% fmin feven)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2405
     (cl-loop for x from start upto (* max factor) by feven
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2406
 	     collect (e/ x factor))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2407
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2408
 (defun eplot--days-to-time (days)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2409
   (days-to-time (- days (time-to-days 0))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2410
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2411
 (defun eplot--get-date-ticks (start end xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2412
 				    x-label-format &optional skip-until)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2413
   (let* ((duration (- end start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2414
 	 (limits
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2415
 	  (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2416
 	   (list (/ 368 16) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2417
 		 (lambda (_d) t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2418
 	   (list (/ 368 4) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2419
 		 ;; Collect Mondays.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2420
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2421
 		   (= (decoded-time-weekday decoded) 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2422
 	   (list (/ 368 2) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2423
 		 ;; Collect 1st and 15th.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2424
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2425
 		   (or (= (decoded-time-day decoded) 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2426
 		       (= (decoded-time-day decoded) 15))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2427
 	   (list (* 368 2) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2428
 		 ;; Collect 1st of every month.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2429
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2430
 		   (= (decoded-time-day decoded) 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2431
 	   (list (* 368 4) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2432
 		 ;; Collect every quarter.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2433
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2434
 		   (and (= (decoded-time-day decoded) 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2435
 			(memq (decoded-time-month decoded) '(1 4 7 10)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2436
 	   (list (* 368 8) 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2437
 		 ;; Collect every half year.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2438
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2439
 		   (and (= (decoded-time-day decoded) 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2440
 			(memq (decoded-time-month decoded) '(1 7)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2441
 	   (list 1.0e+INF 'year
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2442
 		 ;; Collect every Jan 1st.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2443
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2444
 		   (and (= (decoded-time-day decoded) 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2445
 			(= (decoded-time-month decoded) 1)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2446
     ;; First we collect the potential ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2447
     (while (or (>= duration (caar limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2448
 	       (and skip-until (>= skip-until (caar limits))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2449
       (pop limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2450
     (let* ((x-ticks (cl-loop for day from start upto end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2451
 			     for time = (eplot--days-to-time day)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2452
 			     for decoded = (decode-time time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2453
 			     when (funcall (nth 2 (car limits)) decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2454
 			     collect day))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2455
 	   (count (length x-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2456
 	   (print-format (nth 1 (car limits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2457
 	   (max-print (eplot--format-value (car x-ticks) print-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2458
 					   x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2459
 	   (min-spacing (* 1.2 (eplot--text-width max-print label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2460
 						  label-font-size))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2461
       (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2462
        ;; We have room for every X value.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2463
        ((< (* count min-spacing) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2464
 	(list x-ticks print-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2465
        ;; We have to prune X labels, but not grid lines.  (We shouldn't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2466
        ;; have a grid line more than every 10 pixels.)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2467
        ((< (* count 10) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2468
 	(cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2469
 	 ((not (cdr limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2470
 	  (eplot--year-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2471
 	   x-ticks xs label-font label-font-size x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2472
 	 ;; The Mondays grid is special, because it doesn't resolve
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2473
 	 ;; into any of the bigger limits evenly.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2474
 	 ((= (caar limits) (/ 368 4))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2475
 	  (let* ((max-print (eplot--format-value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2476
 			     (car x-ticks) print-format x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2477
 		 (min-spacing (* 1.2 (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2478
 				      max-print label-font label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2479
 		 (weed-factor 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2480
 	    (while (> (* (/ (length x-ticks) weed-factor) min-spacing) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2481
 	      (setq weed-factor (* weed-factor 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2482
 	    (list x-ticks 'date
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2483
 		  (cl-loop for val in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2484
 			   for i from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2485
 			   collect (list val t (zerop (% i weed-factor)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2486
 	 (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2487
 	  (pop limits)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2488
 	  (catch 'found
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2489
 	    (while limits
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2490
 	      (let ((candidate
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2491
 		     (cl-loop for day in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2492
 			      for time = (eplot--days-to-time day)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2493
 			      for decoded = (decode-time time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2494
 			      collect (list day t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2495
 					    (not (not
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2496
 						  (funcall (nth 2 (car limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2497
 							   decoded)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2498
 		(setq print-format (nth 1 (car limits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2499
 		(let* ((max-print (eplot--format-value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2500
 				   (car x-ticks) print-format x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2501
 		       (min-spacing (* 1.2 (eplot--text-width
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2502
 					    max-print label-font
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2503
 					    label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2504
 		       (num-labels (seq-count (lambda (v) (nth 2 v))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2505
 					      candidate)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2506
 		  (when (and (not (zerop num-labels))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2507
 			     (< (* num-labels min-spacing) xs))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2508
 		    (throw 'found (list x-ticks print-format candidate)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2509
 	      (pop limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2510
 	    (eplot--year-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2511
 	     x-ticks xs label-font label-font-size x-label-format)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2512
        ;; We have to reduce both grid lines and labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2513
        (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2514
 	(eplot--get-date-ticks start end xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2515
 			       x-label-format (caar limits)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2516
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2517
 (defun eplot--year-ticks (x-ticks xs label-font label-font-size x-label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2518
   (let* ((year-ticks (mapcar (lambda (day)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2519
 			       (decoded-time-year
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2520
 				(decode-time (eplot--days-to-time day))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2521
 			     x-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2522
 	 (xv (eplot--compute-x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2523
 	      xs year-ticks 'year x-label-format label-font label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2524
     (let ((tick-step (car xv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2525
 	  (label-step (cadr xv)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2526
       (list x-ticks 'year
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2527
 	    (cl-loop for year in year-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2528
 		     for val in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2529
 		     collect (list val
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2530
 				   (zerop (% year tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2531
 				   (zerop (% year label-step))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2532
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2533
 (defun eplot--get-time-ticks (start end xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2534
 				    x-label-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2535
 				    &optional skip-until)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2536
   (let* ((duration (- end start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2537
 	 (limits
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2538
 	  (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2539
 	   (list (* 2 60) 'time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2540
 		 (lambda (_d) t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2541
 	   (list (* 2 60 60) 'time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2542
 		 ;; Collect whole minutes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2543
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2544
 		   (zerop (decoded-time-second decoded))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2545
 	   (list (* 3 60 60) 'minute
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2546
 		 ;; Collect five minutes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2547
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2548
 		   (zerop (% (decoded-time-minute decoded) 5))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2549
 	   (list (* 4 60 60) 'minute
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2550
 		 ;; Collect fifteen minutes.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2551
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2552
 		   (and (zerop (decoded-time-second decoded))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2553
 			(memq (decoded-time-minute decoded) '(0 15 30 45)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2554
 	   (list (* 8 60 60) 'minute
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2555
 		 ;; Collect half hours.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2556
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2557
 		   (and (zerop (decoded-time-second decoded))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2558
 			(memq (decoded-time-minute decoded) '(0 30)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2559
 	   (list 1.0e+INF 'hour
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2560
 		 ;; Collect whole hours.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2561
 		 (lambda (decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2562
 		   (and (zerop (decoded-time-second decoded))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2563
 			(zerop (decoded-time-minute decoded))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2564
     ;; First we collect the potential ticks.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2565
     (while (or (>= duration (caar limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2566
 	       (and skip-until (>= skip-until (caar limits))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2567
       (pop limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2568
     (let* ((x-ticks (cl-loop for time from start upto end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2569
 			     for decoded = (decode-time time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2570
 			     when (funcall (nth 2 (car limits)) decoded)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2571
 			     collect time))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2572
 	   (count (length x-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2573
 	   (print-format (nth 1 (car limits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2574
 	   (max-print (eplot--format-value (car x-ticks) print-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2575
 					   x-label-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2576
 	   (min-spacing (* (+ (length max-print) 2) (e/ label-font-size 2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2577
       (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2578
        ;; We have room for every X value.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2579
        ((< (* count min-spacing) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2580
 	(list x-ticks print-format))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2581
        ;; We have to prune X labels, but not grid lines.  (We shouldn't
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2582
        ;; have a grid line more than every 10 pixels.)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2583
        ;; If we're plotting just seconds, then just weed out some seconds.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2584
        ((and (< (* count 10) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2585
 	     (= (caar limits) (* 2 60)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2586
 	(let ((xv (eplot--compute-x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2587
 		   xs x-ticks 'time x-label-format label-font label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2588
 	  (let ((tick-step (car xv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2589
 		(label-step (cadr xv)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2590
 	    (list x-ticks 'time
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2591
 		  (cl-loop for val in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2592
 			   collect (list val
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2593
 					 (zerop (% val tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2594
 					 (zerop (% val label-step))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2595
        ;; Normal case for pruning labels, but not grid lines.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2596
        ((< (* count 10) xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2597
 	(if (not (cdr limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2598
 	    (eplot--hour-ticks x-ticks xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2599
 			       x-label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2600
 	  (pop limits)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2601
 	  (catch 'found
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2602
 	    (while limits
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2603
 	      (let ((candidate
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2604
 		     (cl-loop for val in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2605
 			      for decoded = (decode-time val)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2606
 			      collect (list val t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2607
 					    (not (not
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2608
 						  (funcall (nth 2 (car limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2609
 							   decoded)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2610
 		(setq print-format (nth 1 (car limits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2611
 		(let ((min-spacing (* (+ (length max-print) 2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2612
 				      (e/ label-font-size 2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2613
 		  (when (< (* (seq-count (lambda (v) (nth 2 v)) candidate)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2614
 			      min-spacing)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2615
 			   xs)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2616
 		    (throw 'found (list x-ticks print-format candidate)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2617
 	      (pop limits))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2618
 	    (eplot--hour-ticks x-ticks xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2619
 			       x-label-format))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2620
        ;; We have to reduce both grid lines and labels.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2621
        (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2622
 	(eplot--get-time-ticks start end xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2623
 			       x-label-format (caar limits)))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2624
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2625
 (defun eplot--hour-ticks (x-ticks xs label-font label-font-size
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2626
 				  x-label-format)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2627
   (let* ((eplot--pleasing-numbers '(1 3 6 12))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2628
 	 (hour-ticks (mapcar (lambda (time)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2629
 			       (decoded-time-hour (decode-time time)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2630
 			     x-ticks))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2631
 	 (xv (eplot--compute-x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2632
 	      xs hour-ticks 'year x-label-format label-font label-font-size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2633
     (let ((tick-step (car xv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2634
 	  (label-step (cadr xv)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2635
       (list x-ticks 'hour
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2636
 	    (cl-loop for hour in hour-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2637
 		     for val in x-ticks
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2638
 		     collect (list val
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2639
 				   (zerop (% hour tick-step))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2640
 				   (zerop (% hour label-step))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2641
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2642
 (defun eplot--int (number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2643
   (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2644
    ((integerp number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2645
     number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2646
    ((= number (truncate number))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2647
     (truncate number))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2648
    (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2649
     number)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2650
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2651
 (defun eplot--pleasing-numbers (number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2652
   (let* ((digits (eplot--decimal-digits number))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2653
 	 (one (e/ 1 (expt 10 digits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2654
 	 (two (e/ 2 (expt 10 digits)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2655
 	 (five (e/ 5 (expt 10 digits))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2656
     (catch 'found
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2657
       (while t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2658
 	(when (< number one)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2659
 	  (throw 'found one))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2660
 	(setq one (* one 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2661
 	(when (< number two)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2662
 	  (throw 'found two))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2663
 	(setq two (* two 10))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2664
 	(when (< number five)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2665
 	  (throw 'found five))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2666
 	(setq five (* five 10))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2667
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2668
 (defun eplot-parse-and-insert (file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2669
   "Parse and insert a file in the current buffer."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2670
   (interactive "fEplot file: ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2671
   (let ((default-directory (file-name-directory file)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2672
     (setq-local eplot--current-chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2673
 		(eplot--render (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2674
 				 (insert-file-contents file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2675
 				 (eplot--parse-buffer))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2676
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2677
 (defun eplot-list-chart-headers ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2678
   "Pop to a buffer showing all chart parameters."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2679
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2680
   (pop-to-buffer "*eplot help*")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2681
   (let ((inhibit-read-only t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2682
     (special-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2683
     (erase-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2684
     (insert "The following headers influence the overall\nlook of the chart:\n\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2685
     (eplot--list-headers eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2686
     (ensure-empty-lines 2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2687
     (insert "The following headers are per plot:\n\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2688
     (eplot--list-headers eplot--plot-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2689
     (goto-char (point-min))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2690
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2691
 (defun eplot--list-headers (headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2692
   (dolist (header (sort (copy-sequence headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2693
 			(lambda (e1 e2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2694
 			  (string< (car e1) (car e2)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2695
     (insert (propertize (capitalize (symbol-name (car header))) 'face 'bold)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2696
 	    "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2697
     (let ((start (point)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2698
       (insert (plist-get (cdr header) :doc) "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2699
       (when-let ((valid (plist-get (cdr header) :valid)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2700
 	(insert "Possible values are: "
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2701
 		(mapconcat (lambda (v) (format "`%s'" v)) valid ", ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2702
 		".\n"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2703
       (indent-rigidly start (point) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2704
     (ensure-empty-lines 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2705
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2706
 (defvar eplot--transients
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2707
   '((("Size"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2708
       ("sw" "Width")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2709
       ("sh" "Height")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2710
       ("sl" "Margin-Left")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2711
       ("st" "Margin-Top")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2712
       ("sr" "Margin-Right")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2713
       ("sb" "Margin-Bottom"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2714
      ("Colors"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2715
       ("ca" "Axes-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2716
       ("cb" "Border-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2717
       ("cc" "Chart-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2718
       ("cf" "Frame-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2719
       ("cs" "Surround-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2720
       ("ct" "Title-Color"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2721
      ("Background"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2722
       ("bc" "Background-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2723
       ("bg" "Background-Gradient")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2724
       ("bi" "Background-Image-File")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2725
       ("bv" "Background-Image-Cover")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2726
       ("bo" "Background-Image-Opacity")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2727
     (("General"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2728
       ("gt" "Title")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2729
       ("gf" "Font")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2730
       ("gs" "Font-Size")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2731
       ("ge" "Font-Weight")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2732
       ("go" "Format")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2733
       ("gw" "Frame-Width")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2734
       ("gh" "Header-File")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2735
       ("gi" "Min")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2736
       ("ga" "Max")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2737
       ("gm" "Mode")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2738
       ("gr" "Reset" eplot--reset-transient)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2739
       ("gv" "Save" eplot--save-transient))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2740
      ("Axes, Grid & Legend"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2741
       ("xx" "X-Title")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2742
       ("xy" "Y-Title")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2743
       ("xf" "Label-Font")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2744
       ("xz" "Label-Font-Size")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2745
       ("xs" "X-Axis-Title-Space")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2746
       ("xl" "X-Label-Format")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2747
       ("xa" "Y-Label-Format")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2748
       ("il" "Grid-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2749
       ("io" "Grid-Opacity")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2750
       ("ip" "Grid-Position")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2751
       ("ll" "Legend")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2752
       ("lb" "Legend-Background-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2753
       ("lo" "Legend-Border-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2754
       ("lc" "Legend-Color"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2755
      ("Plot"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2756
       ("ps" "Style")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2757
       ("pc" "Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2758
       ("po" "Data-Column")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2759
       ("pr" "Data-format")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2760
       ("pn" "Fill-Border-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2761
       ("pi" "Fill-Color")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2762
       ("pg" "Gradient")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2763
       ("pz" "Size")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2764
       ("pm" "Smoothing")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2765
       ("pb" "Bezier-Factor")))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2766
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2767
 (defun eplot--define-transients ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2768
   (cl-loop for row in eplot--transients
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2769
 	   collect (cl-coerce
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2770
 		    (cl-loop for column in row
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2771
 			     collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2772
 			     (cl-coerce
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2773
 			      (cons (pop column)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2774
 				    (mapcar #'eplot--define-transient column))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2775
 			      'vector))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2776
 		    'vector)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2777
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2778
 (defun eplot--define-transient (action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2779
   (list (nth 0 action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2780
 	(nth 1 action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2781
 	;; Allow explicit commands.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2782
 	(or (nth 2 action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2783
 	    ;; Make a command for altering a setting.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2784
 	    (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2785
 	      (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2786
 	      (eplot--execute-transient (nth 1 action))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2787
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2788
 (defun eplot--execute-transient (action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2789
   (with-current-buffer (or eplot--data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2790
     (unless eplot--transient-settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2791
       (setq-local eplot--transient-settings nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2792
     (let* ((name (intern (downcase action)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2793
 	   (spec (assq name (append eplot--chart-headers eplot--plot-headers)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2794
 	   (type (plist-get (cdr spec) :type)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2795
       ;; Sanity check.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2796
       (unless spec
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2797
 	(error "No such header type: %s" name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2798
       (setq eplot--transient-settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2799
 	    (append
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2800
 	     eplot--transient-settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2801
 	     (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2802
 	      (cons
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2803
 	       name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2804
 	       (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2805
 		((eq type 'number)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2806
 		 (read-number (format "Value for %s (%s): " action type)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2807
 		((string-match "color" (downcase action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2808
 		 (eplot--read-color (format "Value for %s (color): " action)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2809
 		((string-match "font" (downcase action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2810
 		 (eplot--read-font-family
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2811
 		  (format "Value for %s (font family): " action)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2812
 		((string-match "gradient" (downcase action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2813
 		 (eplot--read-gradient action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2814
 		((string-match "file" (downcase action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2815
 		 (read-file-name (format "File for %s: " action)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2816
 		((eq type 'symbol)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2817
 		 (intern
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2818
 		  (completing-read (format "Value for %s: " action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2819
 				   (plist-get (cdr spec) :valid)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2820
 				   nil t)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2821
 		(t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2822
 		 (read-string (format "Value for %s (string): " action))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2823
       (eplot-update-view-buffer))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2824
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2825
 (defun eplot--read-gradient (action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2826
   (format "%s %s %s %s"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2827
 	  (eplot--read-color (format "%s from color: " action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2828
 	  (eplot--read-color (format "%s to color: " action))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2829
 	  (completing-read (format "%s direction: " action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2830
 			   '(top-down bottom-up left-right right-left)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2831
 			   nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2832
 	  (completing-read (format "%s position: " action)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2833
 			   '(below above)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2834
 			   nil t)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2835
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2836
 (defun eplot--reset-transient ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2837
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2838
   (with-current-buffer (or eplot--data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2839
     (setq-local eplot--transient-settings nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2840
     (eplot-update-view-buffer)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2841
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2842
 (defun eplot--save-transient (file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2843
   (interactive "FSave parameters to file: ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2844
   (when (and (file-exists-p file)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2845
 	     (not (yes-or-no-p "File exists; overwrite? ")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2846
     (user-error "Exiting"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2847
   (let ((settings (with-current-buffer (or eplot--data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2848
 		    eplot--transient-settings)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2849
     (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2850
       (cl-loop for (name . value) in settings
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2851
 	       do (insert (capitalize (symbol-name name)) ": "
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2852
 			  (format "%s" value) "\n"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2853
       (write-region (point-min) (point-max) file))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2854
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2855
 (defvar-keymap eplot-control-mode-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2856
   "RET" #'eplot-control-update
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2857
   "TAB" #'eplot-control-next-field
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2858
   "C-<tab>" #'eplot-control-next-field
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2859
   "<backtab>" #'eplot-control-prev-field)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2860
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2861
 (define-derived-mode eplot-control-mode special-mode "eplot control"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2862
   (setq-local completion-at-point-functions
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2863
 	      (cons 'eplot--complete-control completion-at-point-functions))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2864
   (add-hook 'before-change-functions #'eplot--process-text-input-before nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2865
   (add-hook 'after-change-functions #'eplot--process-text-value nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2866
   (add-hook 'after-change-functions #'eplot--process-text-input nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2867
   (setq-local nobreak-char-display nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2868
   (setq truncate-lines t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2869
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2870
 (defun eplot--complete-control ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2871
   ;; Complete headers names.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2872
   (when-let* ((input (get-text-property (point) 'input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2873
 	      (name (plist-get input :name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2874
 	      (spec (cdr (assq name (append eplot--plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2875
 					    eplot--chart-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2876
 	      (start (plist-get input :start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2877
 	      (end (- (plist-get input :end) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2878
 	      (completion-ignore-case t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2879
     (skip-chars-backward " " start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2880
     (or
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2881
      (and (eq (plist-get spec :type) 'symbol)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2882
 	  (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2883
 	    (let ((valid (plist-get spec :valid)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2884
 	      (completion-in-region
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2885
 	       (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2886
 		 (skip-chars-backward "^ " start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2887
 		 (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2888
 	       end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2889
 	       (mapcar #'symbol-name valid))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2890
 	      'completion-attempted)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2891
      (and (string-match "color" (symbol-name name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2892
 	  (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2893
 	    (completion-in-region
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2894
 	     (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2895
 	       (skip-chars-backward "^ " start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2896
 	       (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2897
 	     end eplot--colors)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2898
 	    'completion-attempted))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2899
      (and (string-match "\\bfile\\b" (symbol-name name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2900
 	  (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2901
 	    (completion-in-region
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2902
 	     (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2903
 	       (skip-chars-backward "^ " start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2904
 	       (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2905
 	     end (directory-files "."))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2906
 	    'completion-attempted))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2907
      (and (string-match "\\bfont\\b" (symbol-name name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2908
 	  (lambda ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2909
 	    (completion-in-region
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2910
 	     (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2911
 	       (skip-chars-backward "^ " start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2912
 	       (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2913
 	     end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2914
 	     (eplot--font-families))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2915
 	    'completion-attempted)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2916
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2917
 (defun eplot--read-font-family (prompt)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2918
   "Prompt for a font family, possibly offering autocomplete."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2919
   (let ((families (eplot--font-families)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2920
     (if families
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2921
 	(completing-read prompt families)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2922
       (read-string prompt))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2923
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2924
 (defun eplot--font-families ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2925
   (when (executable-find "fc-list")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2926
     (let ((fonts nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2927
       (with-temp-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2928
 	(call-process "fc-list" nil t nil ":" "family")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2929
 	(goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2930
 	(while (re-search-forward "^\\([^,\n]+\\)" nil t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2931
 	  (push (downcase (match-string 1)) fonts)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2932
       (seq-uniq (sort fonts #'string<)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2933
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2934
 (defun eplot-control-next-input ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2935
   "Go to the next input field."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2936
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2937
   (when-let ((match (text-property-search-forward 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2938
     (goto-char (prop-match-beginning match))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2939
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2940
 (defun eplot-control-update ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2941
   "Update the chart based on the current settings."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2942
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2943
   (let ((settings nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2944
     (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2945
       (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2946
       (while-let ((match (text-property-search-forward 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2947
 	(when (equal (get-text-property (prop-match-beginning match) 'face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2948
 		     'eplot--input-changed)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2949
 	  (let* ((name (plist-get (prop-match-value match) :name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2950
 		 (spec (cdr (assq name (append eplot--plot-headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2951
 					       eplot--chart-headers))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2952
 		 (value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2953
 		  (or (plist-get (prop-match-value match) :value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2954
 		      (plist-get (prop-match-value match) :original-value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2955
 	    (setq value (string-trim (string-replace "\u00A0" " " value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2956
 	    (push (cons name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2957
 			(cl-case (plist-get spec :type)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2958
 			  (number
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2959
 			   (string-to-number value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2960
 			  (symbol
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2961
 			   (intern (downcase value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2962
 			  (symbol-list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2963
 			   (mapcar #'intern (split-string (downcase value))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2964
 			  (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2965
 			   value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2966
 		  settings)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2967
     (with-current-buffer eplot--data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2968
       (setq-local eplot--transient-settings (nreverse settings))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2969
       (eplot-update-view-buffer))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2970
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2971
 (defvar eplot--column-width nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2972
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2973
 (defun eplot-create-controls ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2974
   "Pop to a buffer that lists all parameters and allows editing."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2975
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2976
   (with-current-buffer (or eplot--data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2977
     (let ((settings eplot--transient-settings)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2978
 	  (data-buffer (current-buffer))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2979
 	  (chart eplot--current-chart)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2980
 	  ;; Find the max width of all the different names.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2981
 	  (width (seq-max
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2982
 		  (mapcar (lambda (e)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2983
 			    (length (cadr e)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2984
 			  (apply #'append
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2985
 				 (mapcar #'cdr
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2986
 					 (apply #'append eplot--transients))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2987
 	  (transients (mapcar #'copy-sequence
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2988
 			      (copy-sequence eplot--transients))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2989
       (unless chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2990
 	(user-error "Must be called from an eplot buffer that has rendered a chart"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2991
       ;; Rearrange the transients a bit for better display.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2992
       (let ((size (caar transients)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2993
 	(setcar (car transients) (caadr transients))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2994
 	(setcar (cadr transients) size))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2995
       (pop-to-buffer "*eplot controls*")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2996
       (unless (eq major-mode 'eplot-control-mode)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2997
 	(eplot-control-mode))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2998
       (setq-local eplot--data-buffer data-buffer
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2999
 		  eplot--column-width (+ width 12 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3000
       (let ((inhibit-read-only t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3001
 	    (before-change-functions nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3002
 	    (after-change-functions nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3003
 	(erase-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3004
 	(cl-loop for column in transients
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3005
 		 for cn from 0
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3006
 		 do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3007
 		 (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3008
 		 (end-of-line)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3009
 		 (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3010
 		  for row in column
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3011
 		  do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3012
 		  (if (zerop cn)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3013
 		      (when (not (bobp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3014
 			(insert (format (format "%%-%ds" (+ width 14)) "")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3015
 				"\n"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3016
 		    (unless (= (count-lines (point-min) (point)) 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3017
 		      (if (eobp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3018
 			  (progn
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3019
 			    (insert (format (format "%%-%ds" (+ width 14)) "")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3020
 				    "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3021
 			    (insert (format (format "%%-%ds" (+ width 14)) "")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3022
 				    "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3023
 			    (forward-line -1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3024
 			    (end-of-line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3025
 			(forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3026
 			(end-of-line))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3027
 		  ;; If we have a too-long input in the first column,
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3028
 		  ;; then go to the next line.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3029
 		  (when (and (> cn 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3030
 			     (> (- (point) (pos-bol))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3031
 				(+ width 12 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3032
 		    (forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3033
 		    (end-of-line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3034
 		  (insert (format (format "%%-%ds" (+ width 14))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3035
 				  (propertize (pop row) 'face 'bold)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3036
 		  (if (looking-at "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3037
 		      (forward-line 1)				
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3038
 		    (insert "\n"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3039
 		  (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3040
 		   for elem in row
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3041
 		   for name = (cadr elem)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3042
 		   for slot = (intern (downcase name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3043
 		   when (null (nth 2 elem))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3044
 		   do
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3045
 		   (let* ((object (if (assq slot eplot--chart-headers)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3046
 				      chart
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3047
 				    (car (slot-value chart 'plots))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3048
 			  (value (format "%s"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3049
 					 (or (cdr (assq slot settings))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3050
 					     (if (not (slot-boundp object slot))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3051
 						 ""
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3052
 					       (or (slot-value object slot)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3053
 						   ""))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3054
 		     (end-of-line)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3055
 		     ;; If we have a too-long input in the first column,
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3056
 		     ;; then go to the next line.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3057
 		     (when (and (> cn 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3058
 				(> (- (point) (pos-bol))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3059
 				   (+ width 12 2)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3060
 		       (forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3061
 		       (end-of-line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3062
 		     (when (and (> cn 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3063
 				(bolp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3064
 		       (insert (format (format "%%-%ds" (+ width 14)) "") "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3065
 		       (forward-line -1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3066
 		       (end-of-line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3067
 		     (insert (format (format "%%-%ds" (1+ width)) name))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3068
 		     (eplot--input slot value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3069
 				   (if (cdr (assq slot settings))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3070
 				       'eplot--input-changed
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3071
 				     'eplot--input-default))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3072
 		     (if (looking-at "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3073
 			 (forward-line 1)				
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3074
 		       (insert "\n")))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3075
       (goto-char (point-min)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3076
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3077
 (defface eplot--input-default
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3078
   '((t :background "#505050"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3079
        :foreground "#a0a0a0"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3080
        :box (:line-width 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3081
   "Face for eplot default inputs.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3082
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3083
 (defface eplot--input-changed
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3084
   '((t :background "#505050"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3085
        :foreground "white"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3086
        :box (:line-width 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3087
   "Face for eplot changed inputs.")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3088
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3089
 (defvar-keymap eplot--input-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3090
   :full t :parent text-mode-map
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3091
   "RET" #'eplot-control-update
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3092
   "TAB" #'eplot-input-complete
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3093
   "C-a" #'eplot-move-beginning-of-input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3094
   "C-e" #'eplot-move-end-of-input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3095
   "C-k" #'eplot-kill-input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3096
   "C-<tab>" #'eplot-control-next-field
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3097
   "<backtab>" #'eplot-control-prev-field)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3098
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3099
 (defun eplot-input-complete ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3100
   "Complete values in inputs."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3101
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3102
   (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3103
    ((let ((completion-fail-discreetly t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3104
       (completion-at-point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3105
     ;; Completion was performed; nothing else to do.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3106
     nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3107
    ((not (get-text-property (point) 'input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3108
     (eplot-control-next-input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3109
    (t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3110
     (user-error "No completion in this field"))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3111
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3112
 (defun eplot-move-beginning-of-input ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3113
   "Move to the start of the current input field."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3114
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3115
   (if (= (point) (eplot--beginning-of-field))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3116
       (goto-char (pos-bol))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3117
     (goto-char (eplot--beginning-of-field))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3118
   
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3119
 (defun eplot-move-end-of-input ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3120
   "Move to the end of the current input field."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3121
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3122
   (let ((input (get-text-property (point) 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3123
     (if (or (not input)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3124
 	    (= (point) (1- (plist-get input :end))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3125
 	(goto-char (pos-eol))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3126
       (goto-char (1+ (eplot--end-of-field))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3127
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3128
 (defun eplot-control-next-field ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3129
   "Move to the beginning of the next field."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3130
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3131
   (let ((input (get-text-property (point) 'input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3132
 	(start (point)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3133
     (when input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3134
       (goto-char (plist-get input :end)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3135
     (let ((match (text-property-search-forward 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3136
       (if match
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3137
 	  (goto-char (prop-match-beginning match))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3138
 	(goto-char start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3139
 	(user-error "No next field")))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3140
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3141
 (defun eplot-control-prev-field ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3142
   "Move to the beginning of the previous field."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3143
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3144
   (let ((input (get-text-property (point) 'input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3145
 	(start (point)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3146
     (when input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3147
       (goto-char (plist-get input :start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3148
       (unless (bobp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3149
 	(forward-char -1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3150
     (let ((match (text-property-search-backward 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3151
       (unless match
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3152
 	(goto-char start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3153
 	(user-error "No previous field")))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3154
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3155
 (defun eplot-kill-input ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3156
   "Remove the part of the input after point."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3157
   (interactive)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3158
   (let ((end (1+ (eplot--end-of-field))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3159
     (kill-new (string-trim (buffer-substring (point) end)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3160
     (delete-region (point) end)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3161
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3162
 (defun eplot--input (name value face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3163
   (let ((start (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3164
 	input)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3165
     (insert value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3166
     (when (< (length value) 11)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3167
       (insert (make-string (- 11 (length value)) ?\u00A0)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3168
     (put-text-property start (point) 'face face)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3169
     (put-text-property start (point) 'inhibit-read-only t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3170
     (put-text-property start (point) 'input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3171
 		       (setq input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3172
 			     (list :name name
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3173
 				   :size 11
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3174
 				   :is-default (eq face 'eplot--input-default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3175
 				   :original-value value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3176
 				   :original-face face
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3177
 				   :start (set-marker (make-marker) start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3178
 				   :value value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3179
     (put-text-property start (point) 'local-map eplot--input-map)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3180
     ;; This seems like a NOOP, but redoing the properties like this
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3181
     ;; somehow makes `delete-region' work better.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3182
     (set-text-properties start (point) (text-properties-at start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3183
     (insert (propertize " " 'face face
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3184
 			'input input
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3185
 			'inhibit-read-only t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3186
 			'local-map eplot--input-map))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3187
     (plist-put input :end (point-marker))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3188
     (insert " ")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3189
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3190
 (defun eplot--end-of-field ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3191
   (- (plist-get (get-text-property (point) 'input) :end) 2))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3192
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3193
 (defun eplot--beginning-of-field ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3194
   (plist-get (get-text-property (point) 'input) :start))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3195
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3196
 (defvar eplot--prev-deletion nil)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3197
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3198
 (defun eplot--process-text-input-before (beg end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3199
   (message "Before: %s %s" beg end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3200
   (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3201
    ((= beg end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3202
     (setq eplot--prev-deletion nil))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3203
    ((> end beg)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3204
     (setq eplot--prev-deletion (buffer-substring beg end)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3205
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3206
 (defun eplot--process-text-input (beg end _replace-length)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3207
   ;;(message "After: %s %s %s %s" beg end replace-length eplot--prev-deletion)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3208
   (when-let ((props (if eplot--prev-deletion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3209
  			(text-properties-at 0 eplot--prev-deletion)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3210
  		      (if (get-text-property end 'input)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3211
  			  (text-properties-at end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3212
  			(text-properties-at beg))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3213
  	     (input (plist-get props 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3214
     ;; The action concerns something in the input field.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3215
     (let ((buffer-undo-list t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3216
 	  (inhibit-read-only t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3217
 	  (size (plist-get input :size)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3218
       (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3219
 	(set-text-properties beg (- (plist-get input :end) 2) props)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3220
 	(goto-char (1- (plist-get input :end)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3221
 	(let* ((remains (- (point) (plist-get input :start) 1))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3222
 	       (trim (- size remains 1)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3223
 	  (if (< remains size)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3224
 	      ;; We need to add some padding.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3225
 	      (insert (apply #'propertize (make-string trim ?\u00A0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3226
 			     props))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3227
 	    ;; We need to delete some padding, but only delete
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3228
 	    ;; spaces at the end.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3229
 	    (setq trim (abs trim))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3230
 	    (while (and (> trim 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3231
 			(eql (char-after (1- (point))) ?\u00A0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3232
 	      (delete-region (1- (point)) (point))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3233
 	      (cl-decf trim))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3234
 	    (when (> trim 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3235
 	      (eplot--possibly-open-column)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3236
       ;; We re-set the properties so that they are continguous.  This
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3237
       ;; somehow makes the machinery that decides whether we can kill
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3238
       ;; a word work better.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3239
       (set-text-properties (plist-get input :start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3240
 			   (1- (plist-get input :end)) props)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3241
       ;; Compute what the value is now.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3242
       (let ((value (buffer-substring-no-properties
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3243
 		    (plist-get input :start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3244
 		    (plist-get input :end))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3245
 	(when (string-match "\u00A0+\\'" value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3246
 	  (setq value (substring value 0 (match-beginning 0))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3247
 	(plist-put input :value value)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3248
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3249
 (defun eplot--possibly-open-column ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3250
   (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3251
     (when-let ((input (get-text-property (point) 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3252
       (goto-char (plist-get input :end)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3253
     (unless (looking-at " *\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3254
       (skip-chars-forward " ")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3255
       (while (not (eobp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3256
 	(let ((text (buffer-substring (point) (pos-eol))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3257
 	  (delete-region (point) (pos-eol))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3258
 	  (forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3259
 	  (if (eobp)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3260
 	      (insert (make-string eplot--column-width ?\s) text "\n")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3261
 	    (forward-char eplot--column-width)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3262
 	    (if (get-text-property (point) 'input)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3263
 		(forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3264
 	      (insert text)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3265
 	      ;; We have to fix up the markers.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3266
 	      (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3267
 		(let* ((match (text-property-search-backward 'input))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3268
 		       (input (prop-match-value match)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3269
 		  (plist-put input :start
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3270
 			     (set-marker (plist-get input :start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3271
 					 (prop-match-beginning match)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3272
 		  (plist-put input :end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3273
 			     (set-marker (plist-get input :end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3274
 					 (+ (prop-match-end match) 1))))))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3275
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3276
 (defun eplot--process-text-value (beg _end _replace-length)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3277
   (when-let* ((input (get-text-property beg 'input)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3278
     (let ((inhibit-read-only t))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3279
       (when (plist-get input :is-default)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3280
 	(put-text-property (plist-get input :start)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3281
 			   (plist-get input :end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3282
 			   'face
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3283
 			   (if (equal (plist-get input :original-value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3284
 				      (plist-get input :value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3285
 			       'eplot--input-default
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3286
 			     'eplot--input-changed))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3287
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3288
 (defun eplot--read-color (prompt)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3289
   "Read an SVG color."
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3290
   (completing-read prompt eplot--colors))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3291
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3292
 (eval `(transient-define-prefix eplot-customize ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3293
 	 "Customize Chart"
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3294
 	 ,@(eplot--define-transients)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3295
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3296
 (defun eplot--bezier (factor i points)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3297
   (cl-labels ((padd (p1 p2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3298
 		(cons (+ (car p1) (car p2)) (+ (cdr p1) (cdr p2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3299
 	      (psub (p1 p2)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3300
 		(cons (- (car p1) (car p2)) (- (cdr p1) (cdr p2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3301
 	      (pscale (factor point)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3302
 		(cons (* factor (car point)) (* factor (cdr point)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3303
     (let* ((start (elt points (1- i)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3304
 	   (end (elt points i))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3305
 	   (prev (if (< (- i 2) 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3306
 		     start
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3307
 		   (elt points (- i 2))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3308
 	   (next (if (> (1+ i) (1- (length points)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3309
 		     end
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3310
 		   (elt points (1+ i))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3311
 	   (start-control-point
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3312
 	    (padd start (pscale factor (psub end prev))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3313
 	   (end-control-point
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3314
 	    (padd end (pscale factor (psub start next)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3315
       (list (car start-control-point)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3316
 	    (cdr start-control-point)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3317
 	    (car end-control-point)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3318
 	    (cdr end-control-point)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3319
 	    (car end)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3320
 	    (cdr end)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3321
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3322
 ;;; CSV Parsing Stuff.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3323
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3324
 (defun eplot--csv-buffer-p ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3325
   (save-excursion
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3326
     (goto-char (point-min))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3327
     (let ((min 1.0e+INF)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3328
 	  (max -1.0e+INF)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3329
 	  (total 0)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3330
 	  (lines 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3331
       (while (not (eobp))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3332
 	(let ((this 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3333
 	  (while (search-forward "," (pos-eol) t)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3334
 	    (cl-incf total)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3335
 	    (cl-incf this))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3336
 	  (forward-line 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3337
 	  (cl-incf lines)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3338
 	  (setq min (min min this)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3339
 		max (max max this))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3340
       (let ((mid (e/ total lines)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3341
 	;; If we have a comma on each line, and it's fairly evenly
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3342
 	;; distributed, it's a CSV buffer.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3343
 	(and (>= min 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3344
 	     (< (* mid 0.9) min)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3345
 	     (> (* mid 1.1) max))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3346
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3347
 (defun eplot--numericalp (value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3348
   (string-match-p "\\`[-.0-9]*\\'" value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3349
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3350
 (defun eplot--numberish (value)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3351
   (if (or (zerop (length value))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3352
 	  (not (eplot--numericalp value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3353
       value
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3354
     (string-to-number value)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3355
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3356
 (defun eplot--parse-csv-buffer ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3357
   (unless (fboundp 'pcsv-parse-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3358
     (user-error "You need to install the pcsv package to parse CSV files"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3359
   (let ((csv (and (fboundp 'pcsv-parse-buffer)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3360
 		  ;; This repeated check is just to silence the byte
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3361
 		  ;; compiler.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3362
 		  (pcsv-parse-buffer)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3363
 	names)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3364
     ;; Check whether the first line looks like a header.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3365
     (when (and (length> csv 1)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3366
 	       ;; The second line is all numbers...
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3367
 	       (cl-every #'eplot--numericalp (nth 1 csv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3368
 	       ;; .. and the first line isn't.
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3369
 	       (not (cl-every #'eplot--numericalp (nth 0 csv))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3370
       (setq names (pop csv)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3371
     (list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3372
      (cons 'legend (and names "true"))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3373
      (cons :plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3374
 	   (cl-loop
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3375
 	    for column from 1 upto (1- (length (car csv)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3376
 	    collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3377
 	    (list (cons :headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3378
 			(list
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3379
 			 (cons 'name (elt names column))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3380
 			 (cons 'data-format
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3381
 			       (cond
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3382
 				((cl-every (lambda (e) (<= (length e) 4))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3383
 					   (mapcar #'car csv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3384
 				 "year")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3385
 				((cl-every (lambda (e) (= (length e) 8))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3386
 					   (mapcar #'car csv))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3387
 				 "date")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3388
 				(t
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3389
 				 "number")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3390
 			 (cons 'color (eplot--vary-color "vary" (1- column)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3391
 		  (cons
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3392
 		   :values
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3393
 		   (cl-loop for line in csv
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3394
 			    collect (list :x (eplot--numberish (car line))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3395
 					  :value (eplot--numberish
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3396
 						  (elt line column)))))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3397
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3398
 (declare-function org-element-parse-buffer "org-element")
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3399
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3400
 (defun eplot--parse-org-buffer ()
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3401
   (require 'org-element)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3402
   (let* ((table (nth 2 (nth 2 (org-element-parse-buffer))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3403
 	 (columns (cl-loop for cell in (nthcdr 2 (nth 2 table))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3404
 			   collect (substring-no-properties (nth 2 cell))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3405
 	 (value-column (or (seq-position columns "value") 0))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3406
 	 (date-column (seq-position columns "date")))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3407
     `((:plots
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3408
        ((:headers
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3409
 	 ,@(and date-column '((data-format . "date"))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3410
 	(:values 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3411
 	 ,@(cl-loop for row in (nthcdr 4 table)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3412
 		    collect
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3413
 		    (let ((cells (cl-loop for cell in (nthcdr 2 row)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3414
 					  collect (substring-no-properties
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3415
 						   (nth 2 cell)))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3416
 		      (list :value (string-to-number (elt cells value-column))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3417
 			    :x (string-to-number
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3418
 				(replace-regexp-in-string
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3419
 				 "[^0-9]" "" (elt cells date-column)))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3420
 			    )))))))))
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3421
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3422
 (provide 'eplot)
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3423
 
f61dc77440df add eplot.el
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3424
 ;;; eplot.el ends here