summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Shangreaux <grant@unabridgedsoftware.com>2022-11-11 21:41:12 -0600
committerGrant Shangreaux <grant@unabridgedsoftware.com>2022-11-11 21:41:12 -0600
commitd63b8422e2fc63fe7a94358c142f53f04fd02d62 (patch)
tree4c1beb7b17933c15b6737a86683f862cf7583306
Add: inital commit of WIP coorgi-client.org literate program
- emacs package template comments - add cl-lib dependency - add coorg-properties defvar - add coorgify-at-point wip implementation - add test org docs for coorgify-at-point
-rw-r--r--coorgi-client.org272
1 files changed, 272 insertions, 0 deletions
diff --git a/coorgi-client.org b/coorgi-client.org
new file mode 100644
index 0000000..4844c31
--- /dev/null
+++ b/coorgi-client.org
@@ -0,0 +1,272 @@
+#+PROPERTY: header-args:emacs-lisp :lexical t
+
+* Coorgi Client - A collaborative org document sync client.
+
+#+begin_src emacs-lisp :tangle yes :noweb no-export
+ ;;; coorgi-client.el --- A collaborative org document sync client. -*- lexical-binding: t; -*-
+
+ <<copyright>>
+
+ <<license>>
+
+ <<dependencies>>
+ <<defvars>>
+ <<coorgi--find-heading>>
+ <<coorgify-at-point>>
+
+ ;;; coorgi-client.el ends here
+#+end_src
+
+* dependencies
+
+#+begin_src emacs-lisp :tangle yes :results none :noweb-ref dependencies
+ (require 'cl-lib)
+#+end_src
+
+* defvars
+:PROPERTIES:
+:header-args:emacs-lisp+: :noweb-ref defvars :noweb-sep "\n\n" :results silent
+:END:
+
+** coorgi-properties
+
+This variable stores a list of upcased symbols that appear in the headline
+element's parsed property drawer.
+
+#+begin_src emacs-lisp :tangle yes :results none
+ (defvar coorgi-properties '(:COORGI-KEY
+ :COORGI-LAST-MODIFIED
+ :COORGI-LAST-MODIFIED-BY
+ :COORGI-VERSION)
+ "List of properties coorgi cares about.")
+#+end_src
+
+* Functions
+** coorgify-at-point
+
+Converts the current org outline section into a coorgi-node data structure.
+
+#+name: coorgify-at-point
+#+begin_src emacs-lisp :results none
+ (defun coorgify-at-point ()
+ (save-excursion
+ (let* ((current-element (org-element-at-point))
+ (entry (if (not (equal (car current-element) 'heading))
+ (progn (org-up-heading-safe)
+ (org-element-at-point))
+ current-element))
+ (parsed (print (org-element-parse-buffer)))
+ (props (org-element--get-node-properties))
+ (non-coorgi-props (cl-loop for (key value) on props by #'cddr
+ unless (member key coorgi-properties)
+ append (list key value)))
+ (content-bounds (cons (progn (org-down-element) (org-forward-element) (point)) (plist-get (cadr entry) :contents-end))))
+ `( type entry
+ headline ,(plist-get (cadr entry) :title)
+ version ,(string-to-number (plist-get props :COORGI-VERSION))
+ last-modified-by ,(plist-get props :COORGI-LAST-MODIFIED-BY)
+ last-modified ,(plist-get props :COORGI-LAST-MODIFIED)
+ key ,(plist-get props :COORGI-KEY)
+ properties ,non-coorgi-props
+ contents ,(buffer-substring-no-properties (car content-bounds) (cdr content-bounds))))))
+#+end_src
+
+*** helpers
+**** coorgi--find-heading
+
+We need to used the parsed version of the org buffer to look up the elements
+we're turning into coorgi nodes and get the relevant data to pack it up recursively.
+
+#+name: coorgi--find-heading
+#+begin_src emacs-lisp :results none
+ (defun coorgi--find-heading (heading org-data)
+ (car (org-element-map org-data 'headline
+ (lambda (hl)
+ (when (string-equal (org-element-property :raw-value hl)
+ (org-element-property :raw-value heading))
+ hl)))))
+#+end_src
+
+#+begin_src emacs-lisp :var org-doc=trivial-example() :results code
+ (let ((org-data (with-temp-buffer (insert org-doc) (org-element-parse-buffer))))
+ (coorgi--find-heading '(headline (:raw-value "MOO")) org-data))
+#+end_src
+
+#+RESULTS:
+#+begin_src emacs-lisp
+(headline
+ (:raw-value "MOO" :begin 1 :end 142 :pre-blank 0 :contents-begin 7 :contents-end 142 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 1 :FOO "bar" :COORGI-KEY "101" :COORGI-LAST-MODIFIED "123" :COORGI-LAST-MODIFIED-BY "colin/123" :COORGI-VERSION "1" :title
+ (#("MOO" 0 3
+ (:parent #0)))
+ :parent
+ (org-data nil #0))
+ (section
+ (:begin 7 :end 142 :contents-begin 7 :contents-end 142 :post-blank 0 :post-affiliated 7 :parent #0)
+ (property-drawer
+ (:begin 7 :end 136 :contents-begin 20 :contents-end 129 :post-blank 1 :post-affiliated 7 :parent #1)
+ (node-property
+ (:key "coorgi-version" :value "1" :begin 20 :end 39 :post-blank 0 :post-affiliated 20 :parent #2))
+ (node-property
+ (:key "coorgi-last-modified-by" :value "colin/123" :begin 39 :end 75 :post-blank 0 :post-affiliated 39 :parent #2))
+ (node-property
+ (:key "coorgi-last-modified" :value "123" :begin 75 :end 102 :post-blank 0 :post-affiliated 75 :parent #2))
+ (node-property
+ (:key "coorgi-key" :value "101" :begin 102 :end 119 :post-blank 0 :post-affiliated 102 :parent #2))
+ (node-property
+ (:key "foo" :value "bar" :begin 119 :end 129 :post-blank 0 :post-affiliated 119 :parent #2)))
+ (paragraph
+ (:begin 136 :end 142 :contents-begin 136 :contents-end 142 :post-blank 0 :post-affiliated 136 :parent #1)
+ #("hello\n" 0 6
+ (:parent #2)))))
+#+end_src
+
+*** Testing
+
+**** Trivial Org Example
+
+Given this org document:
+
+#+name: trivial-example
+#+begin_src org
+,* MOO
+:PROPERTIES:
+:coorgi-version: 1
+:coorgi-last-modified-by: colin/123
+:coorgi-last-modified: 123
+:coorgi-key: 101
+:foo: bar
+:END:
+
+hello
+
+#+end_src
+
+~coorgify-at-point~ should return something like this:
+
+#+name: trivial-expected-value
+#+begin_src emacs-lisp
+ '(type entry
+ headline "MOO"
+ version 1
+ last-modified-by "colin/123"
+ last-modified "123"
+ key "101"
+ properties (:FOO "bar")
+ content "
+ hello
+
+ "
+ children ())
+#+end_src
+
+No matter where the cursor is in the buffer (there's only one coorgi node)
+
+***** TODO When the cursor is in the body of the heading
+
+#+name: test-trivial-example-cursor-in-body
+#+begin_src emacs-lisp :var org-doc=trivial-example() expected=trivial-expected-value :results code
+ (let ((subject (with-temp-buffer (insert org-doc) (coorgify-at-point))))
+ (if (not (equal subject expected))
+ `((actual ,subject) (expected ,expected))
+ "PASS"))
+#+end_src
+
+#+RESULTS: test-trivial-example-cursor-in-body
+#+begin_src emacs-lisp
+((actual
+ (type entry headline "MOO" version 1 last-modified-by "colin/123" last-modified "123" key "101" properties
+ (:FOO "bar")
+ contents "hello\n"))
+ (expected
+ (type entry headline "MOO" version 1 last-modified-by "colin/123" last-modified "123" key "101" properties
+ (:FOO "bar")
+ content "\n\nhello\n\n" children nil)))
+#+end_src
+
+***** TODO When the cursor at the top of the document
+
+#+name: test-trivial-example-cursor-at-top
+#+begin_src emacs-lisp :var org-doc=trivial-example() expected=trivial-expected-value :results code
+ (let ((subject (with-temp-buffer (insert org-doc) (beginning-of-buffer) (coorgify-at-point))))
+ (if (not (equal subject expected))
+ `((actual ,subject) (expected ,expected))
+ "PASS"))
+#+end_src
+
+#+RESULTS: test-trivial-example-cursor-at-top
+#+begin_src emacs-lisp
+((actual
+ (type entry headline "MOO" version 1 last-modified-by "colin/123" last-modified "123" key "101" properties
+ (:FOO "bar")))
+ (expected
+ (type entry headline "MOO" version 1 last-modified-by "colin/123" last-modified "123" key "101" properties
+ (:FOO "bar")
+ content "\n\nhello\n\n" children nil)))
+#+end_src
+
+**** Basic Org Example
+
+#+name: basic-example
+#+begin_src org
+,* MOO
+:PROPERTIES:
+:coorgi-version: 211
+:coorgi-last-modified-by: “colin/1231234123”
+:coorgi-last-modified: 123124331
+:coorgi-key: “1010101010101”
+:foo: “bar”
+:END:
+
+hello
+
+,** TODO [#B] Cow :foobar:
+:PROPERTIES:
+:coorgi-version: 32
+:coorgi-last-modified-by: “colin/1231234123”
+:coorgi-last-modified: 123124331
+:coorgi-key: “123sdfas3wasd”
+:foo: “bar”
+:END:
+
+Cows say moo. CURSORPOSITION
+
+,*** Hunky
+
+a cow
+
+,*** Dory
+
+another cow
+#+end_src
+
+* Copyright
+
+#+begin_src emacs-lisp :noweb-ref copyright
+ ;; Copyright (C) 2022 Grant Shangreaux
+
+ ;; Author: Grant Shangreaux <shoshin@cicadas.surf>
+ ;; Maintainer: Grant Shangreaux <shoshin@cicadas.surf>
+ ;; Created: 11 Nov 2022
+ ;; Keywords: org sync collaborative
+ ;; URL: https://cicadas.surf/cgit/coorgi-client.git
+#+end_src
+
+* License
+** GNU General Public License version 3
+
+#+begin_src emacs-lisp :noweb-ref license
+ ;; This file is not part of GNU Emacs.
+
+ ;; This file is free software: you can redistribute it and/or modify
+ ;; it under the terms of the GNU General Public License as published by
+ ;; the Free Software Foundation, either version 3 of the License, or
+ ;; (at your option) any later version.
+ ;;
+ ;; GNU Emacs is distributed in the hope that it will be useful,
+ ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ;; GNU General Public License for more details.
+ ;;
+ ;; You should have received a copy of the GNU General Public License
+ ;; along with this file. If not, see <https://www.gnu.org/licenses/>.
+#+end_src