-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathtiddlywiki-mode.el
189 lines (167 loc) · 6.67 KB
/
tiddlywiki-mode.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
;; TODO
;; method for creating new tid file directly from emacs = generate .tid and add header stuff
(defvar tiddlywiki-org-mode-mimetype "text/org")
(defun tiddlywiki-timestamp ()
(format-time-string "%Y%m%d%H%M%S%3N"))
(defun tiddlywiki-org-mode-tiddler-preamble (title)
"returns a default preamble section for org-mode content type"
(format "created: %s
modified: %s
tags:
title: %s
type: %s"
(tiddlywiki-timestamp)
(tiddlywiki-timestamp)
title
tiddlywiki-org-mode-mimetype))
(defun tiddlywiki-create-new-tiddler (file-path title)
"create a new tiddler with given file path and title"
(find-file-literally file-path)
(insert
(format
"%s\n\n"
(tiddlywiki-org-mode-tiddler-preamble title)))
(tiddlywiki-mode))
(defun tiddlywiki-parse-tid-file ()
(interactive)
(save-excursion
(beginning-of-buffer)
(let ((prop-list nil)
(content nil)
(in-header t))
(while in-header
(if (looking-at "^\\([^\s]+\\):[[:space:]]+?\\(.+\\)$")
;; in header
(setq prop-list (plist-put prop-list (intern (match-string 1))
(match-string 2)))
;; end read header
(setq in-header nil))
(forward-line))
(setq prop-list (plist-put prop-list :header-end-point (point)))
(setq prop-list (plist-put prop-list :header-line-count (- (line-number-at-pos) 2)))
(setq prop-list (plist-put prop-list :content (buffer-substring (point) (point-max))))
prop-list)))
(defun tiddlywiki-narrow-file ()
(interactive)
;; TODO update so it returns silently for non-tid files, so we can add to revert hook
(save-excursion
(widen)
(let ((info (tiddlywiki-parse-tid-file)))
(if (> 1 (plist-get info :header-line-count))
(when (= 0 (buffer-size))
;; there is no preamble/metadata section. Assume this is a new file,
;; and create the preamble.
(progn
(message "No preamble found, creating one...")
(insert (tiddlywiki-org-mode-tiddler-preamble (file-name-base (buffer-name)))
"\n\n")
;; re-set the content type
(setq info (plist-put info 'type tiddlywiki-org-mode-mimetype))))
;; assume existing tiddler with correct header information
(goto-line (+ (plist-get info :header-line-count) 2)))
(narrow-to-region (point) (point-max))
;; edit mode dispatch
(let ((ftype (plist-get info 'type)))
(cond ((string= ftype tiddlywiki-org-mode-mimetype)
(message "org-mode file")
(org-mode))
((string= ftype "text/x-markdown")
(message "markdown file")
(markdown-mode))
((string= ftype "application/javascript")
(message "javascript source")
(js2-mode))
((string= ftype "application/js")
(message "executable javascript")
(js2-mode))
((string= ftype "application/json")
(message "json source")
(javascript-mode))
((string= ftype "text/css")
(message "css source")
(css-mode))
((string= ftype "text/html")
(message "html source")
(html-mode))
((string= ftype "text/vnd.tiddlywiki")
(message "tiddlywiki WikiText")
;; FIXME fixme1
(markdown-mode))
(t
(message (concat "unhandled mode: " type))))))))
(defun tiddlywiki-widen-file ()
(interactive)
(widen)
(text-mode)
(recenter-top-bottom))
(defun tiddlywiki-set-header-read-only ()
(interactive)
(let ((info (tiddlywiki-parse-tid-file))
(modified (buffer-modified-p)))
(let ((ov (make-overlay (point-min) (plist-get info :header-end-point))))
(overlay-put ov 'face '(:background "orange4")))
;; prevent front of first header char still being editable
(put-text-property 1 2 'front-sticky t)
(put-text-property 1 2 'rear-nonsticky nil)
;; prevent front of first non-header being uneditable
(put-text-property (1- (plist-get info :header-end-point))
(plist-get info :header-end-point)
'rear-nonsticky t)
(add-text-properties (point-min) (plist-get info :header-end-point)
'(read-only t face warning))
(set-buffer-modified-p modified)))
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Read-Only-Buffers.html#Read-Only-Buffers
(defun tiddlywiki-unset-header-read-only ()
(interactive)
(let ((info (tiddlywiki-parse-tid-file))
(cur-inhibit-read-only inhibit-read-only)
(modified (buffer-modified-p)))
(setq inhibit-read-only t)
(remove-text-properties (point-min) (plist-get info :header-end-point) '(read-only t face warning))
(setq inhibit-read-only cur-inhibit-read-only)
(remove-overlays (point-min) (plist-get info :header-end-point))
(set-buffer-modified-p modified)))
(defun tiddlywiki-create-new-tiddler
(path title)
"create a new tiddler with given file path and title"
(find-file path)
(insert
(format "%s\n\n"
(tiddlywiki-org-mode-tiddler-preamble title)))
(tiddlywiki-mode))
(defun tiddlywiki-org-mode-hook ()
(tiddlywiki-set-header-read-only))
(define-derived-mode tiddlywiki-org-mode
org-mode "TiddlyWiki-org"
"TiddlyWiki+org interaction mode"
(progn
(tiddlywiki-set-header-read-only)
(tiddlywiki-narrow-file)
))
;; (add-to-list 'auto-mode-alist '("\\.org.tid\\'" . tiddlywiki-org-mode))
(defun tiddlywiki-update-modified-time ()
(when (string= "tid" (file-name-extension (buffer-file-name)))
(tiddlywiki-unset-header-read-only)
(save-excursion
(beginning-of-buffer)
(search-forward "modified: ")
(delete-region (point) (line-end-position))
(insert (tiddlywiki-timestamp)))
(tiddlywiki-set-header-read-only)))
(add-hook 'before-save-hook 'tiddlywiki-update-modified-time)
;; (add-hook 'org-mode-hook
;; (lambda ()
;; (add-hook 'before-save-hook 'tiddlywiki-update-modified-time nil 'make-it-local)))
(define-derived-mode tiddlywiki-mode
fundamental-mode "TiddlyWiki"
"TiddlyWiki interaction mode"
(progn
(tiddlywiki-set-header-read-only)
(tiddlywiki-narrow-file)
;; TODO: look into reapplying narrow file after auto revert
;; ref http://www.gnu.org/software/emacs/manual/html_node/elisp/Reverting.html
(auto-revert-mode)))
(add-to-list 'auto-mode-alist '("\\.tid\\'" . tiddlywiki-mode))
;; add after fix non-tid detect
;; (add-hook 'after-revert-hook 'tiddlywiki-narrow-file)
(provide 'tiddlywiki-mode)