From d97540a4c4493c8788533a3cf5fa08fdafa4ffa2 Mon Sep 17 00:00:00 2001 From: Andy Stewart Date: Fri, 28 Feb 2020 16:14:04 +0800 Subject: [PATCH] Move eaf mindmap code to eaf-mindmap.el --- app/mindmap/eaf-mindmap.el | 307 +++++++++++++++++++++++++++++++++++++ eaf.el | 219 +------------------------- 2 files changed, 308 insertions(+), 218 deletions(-) create mode 100644 app/mindmap/eaf-mindmap.el diff --git a/app/mindmap/eaf-mindmap.el b/app/mindmap/eaf-mindmap.el new file mode 100644 index 0000000..3a4a905 --- /dev/null +++ b/app/mindmap/eaf-mindmap.el @@ -0,0 +1,307 @@ +;;; eaf-mindmap.el --- Simple description + +;; Filename: eaf-mindmap.el +;; Description: Simple description +;; Author: Andy Stewart +;; Maintainer: Andy Stewart +;; Copyright (C) 2020, Andy Stewart, all rights reserved. +;; Created: 2020-02-28 16:09:02 +;; Version: 0.1 +;; Last-Updated: 2020-02-28 16:09:02 +;; By: Andy Stewart +;; URL: http://www.emacswiki.org/emacs/download/eaf-mindmap.el +;; Keywords: +;; Compatibility: GNU Emacs 26.3 +;; +;; Features that might be required by this library: +;; +;; +;; + +;;; This file is NOT part of GNU Emacs + +;;; License +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth +;; Floor, Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; Simple description +;; + +;;; Installation: +;; +;; Put eaf-mindmap.el to your load-path. +;; The load-path is usually ~/elisp/. +;; It's set in your ~/.emacs like this: +;; (add-to-list 'load-path (expand-file-name "~/elisp")) +;; +;; And the following to your ~/.emacs startup file. +;; +;; (require 'eaf-mindmap) +;; +;; No need more. + +;;; Customize: +;; +;; +;; +;; All of the above can customize by: +;; M-x customize-group RET eaf-mindmap RET +;; + +;;; Change log: +;; +;; 2020/02/28 +;; * First released. +;; + +;;; Acknowledgements: +;; +;; +;; + +;;; TODO +;; +;; +;; + +;;; Require +(require 'json) + +;;; Code: + +(dbus-register-signal + :session "com.lazycat.eaf" "/com/lazycat/eaf" + "com.lazycat.eaf" "export_org_json" + #'eaf--export-org-json) + +(defun eaf--export-org-json (org-json-content org-file-path) + (let (org-parse-data) + (with-temp-buffer + (insert org-json-content) + (beginning-of-buffer) + (let* ((json (json-read)) + (root-node-name (cdr (assoc 'topic (assoc 'data json)))) + (children-node (cdr (assoc 'children (assoc 'data json))))) + ;; (message "%s" (org-json-decode (cdr (assoc 'data json)))) + (insert (org-json-decode (cdr (assoc 'data json)))) + (beginning-of-buffer) + (while (search-forward-regexp "\\*\\s-topic\\s-\"" nil t) + (let ((header-string (buffer-substring (save-excursion + (beginning-of-line) + (point)) + (save-excursion + (beginning-of-line) + (search-forward-regexp "\\*\\s-" nil t) + (point) + ))) + (content-string (buffer-substring (point) + (save-excursion + (end-of-line) + (backward-char 1) + (point))))) + (when (> (length header-string) 2) + (setq header-string (string-remove-prefix "*" header-string))) + (setq org-parse-data (concat org-parse-data (format "%s%s\n" header-string content-string))))) + + (with-temp-file org-file-path + (insert org-parse-data)) + )))) + +(defun json-read-r () + (let ((json-object-type 'alist)) + (let ((r (json-read))) + (if (listp r) (reverse r) r)))) + +(defun org-json-raw () + (let (p1) + (goto-char (point-min)) + (re-search-forward "[ \n\t]*") + (beginning-of-line) + (delete-region (point-min) (point)) + (if (re-search-forward "\\`#\\+begin_src" nil t) + ;; string + (progn + (if (re-search-forward "^#\\+end_src" nil t) + (progn (beginning-of-line) + (setq p1 (point))) + (setq p1 (point-max))) + (goto-char (point-min)) + (forward-line 1) + (buffer-substring-no-properties (point) p1)) + (goto-char (point-min)) + (json-read-r)))) + +(defun org-json-entry (str) + (let (lv header has-body p0 p1) + (with-temp-buffer + (insert str) + (goto-char (point-min)) + (end-of-line) + (setq header (buffer-substring (point-min) (point))) + ;; delete header + (delete-region (point-min) (point)) + ;; process header + (string-match "^\\(\\*+\\) +\\(.+?\\) *$" header) + (setq lv (length (match-string 1 header))) + ;; remove '*' + (setq header (match-string 2 header)) + (goto-char (point-min)) + (if (re-search-forward "\\`[ \n\t]*\\'" nil t) + (list lv header) ; body is empty + (list lv header (org-json-raw)))))) + +(defun org-json-entries () + (let (p0 pl) + ;; get all entries + (setq pl (let (ret tmp) + (goto-char (point-min)) + (while (re-search-forward "^\*+ " nil t) + (setq tmp (point)) + (beginning-of-line) + (setq ret (cons (point) ret)) + (goto-char tmp)) + (setq ret (cons (point-max) ret)) + (reverse ret))) + (setq p0 (car pl)) + (mapcar (lambda (p1) + (prog1 (org-json-entry + (buffer-substring-no-properties p0 p1)) + (setq p0 p1))) + (cdr pl)))) + +(defun org-json-split-header (lst &optional ret) + "Split header for the return of `org-json-entries'." + (if (null lst) (reverse ret) + (let (e0 e1 lst1) + (setq e0 (car lst)) + (setq lst1 (cdr lst)) + (setq e1 (if lst1 (car lst1) + '(0 "" ""))) + (if (>= (car e0) (car e1)) + ;; no child + (when (= (length e0) 2) + ;; split header + (if (string-match "^\\(.+?\\)[ \n\t]+\\(.+\\)$" (nth 1 e0)) + (setq e0 (list (nth 0 e0) + (match-string 1 (nth 1 e0)) + (with-temp-buffer + (insert (match-string 2 (nth 1 e0))) + (goto-char (point-min)) + (json-read-r)))) + (setq e0 (list (nth 0 e0) (nth 1 e0) :json-null)))) + (when (> (length e0) 2) + ;; drop unnecessary elem + (setq e0 (list (nth 0 e0) + (nth 1 e0))))) + (org-json-split-header lst1 (cons e0 ret))))) + +(defun org-json-gen-alist (lst) + "generate alist from return of `org-json-gen-alist', +actural call `org-json-gen-alist1' to work." + (cdr (org-json-gen-alist1 lst 1))) + +(defun org-json-gen-alist1 (lst lv &optional ret) + (if (or (null lst) + (< (car (car lst)) lv)) + ;; return list . ret + (cons lst (reverse ret)) + ;; not return + (let (e r1 kv) + ;; r1 is return of children + ;; kv is key-value pair + (setq e (car lst)) + (if (> (length e) 2) + ;; no child + (progn (setq kv (cons (nth 1 e) + (nth 2 e))) + (org-json-gen-alist1 (cdr lst) lv (cons kv ret))) + + (setq r1 (org-json-gen-alist1 (cdr lst) (1+ lv))) + ;; convert to array if necessray + (let ((seq (mapcar 'car (cdr r1)))) + (when (equal (mapcar 'number-to-string + (number-sequence 0 (1- (length seq)))) + seq) + (setq r1 (cons (car r1) + (vconcat (mapcar 'cdr (cdr r1))))))) + (setq kv (cons (nth 1 e) (cdr r1))) + (org-json-gen-alist1 (car r1) lv + (cons kv ret)))))) + + +(defun org-json-encode () + (save-excursion + (org-json-gen-alist + (org-json-split-header + (org-json-entries))))) + +(defun org-json-decode (obj &optional lv) + "Decode json object to org at level `lv'." + (unless lv (setq lv 1)) + (cond ((stringp obj) (if (string-match "\n\\'" obj) + ;; end with '\n' using #+begin_src block + (concat "#+begin_src\n" + obj + "#+end_src") + (concat "\"" + (replace-regexp-in-string + "\"" "\\\"" + (replace-regexp-in-string + "\\\\" "\\\\" obj)) + "\""))) + ((numberp obj) (number-to-string obj)) + ((vectorp obj) (if (= (length obj) 0) + "[]" + (let ((n 0) ns) + (mapconcat + (lambda (x) + (prog1 + (org-json-kv-decode + (cons (number-to-string n) + x) + lv) + (setq n (1+ n)))) + obj "\n")))) + ((equal obj json-null) "{}") + ((listp obj) (mapconcat + (lambda (x) + (org-json-kv-decode x lv)) + obj "\n")) + ((equal obj t) "true") + ((equal obj json-false) "false") + (t (error "org-json-decode type error: %S" obj)))) + +(defun org-json-kv-decode (kv lv) + "Decode a key-value pair." + (let ((k (car kv)) + (v (cdr kv)) + h ks vs) + (setq ks (cond ((symbolp k) (symbol-name k)) + ((stringp k) k) + ((numberp k) (number-to-string k)) + (t (error "org-json-kv-decode key type error: %S" k)))) + (setq h (concat (make-string lv ?*) " " ks)) + (setq vs (org-json-decode v (1+ lv))) + (if (string-match "\n" vs) + (concat h "\n" vs) + (concat h " " vs)) + )) + +(provide 'eaf-mindmap) + +;;; eaf-mindmap.el ends here diff --git a/eaf.el b/eaf.el index 2ecd68b..8a30f66 100644 --- a/eaf.el +++ b/eaf.el @@ -77,6 +77,7 @@ (require 'map) (require 'bookmark) (require 'seq) +(require 'eaf-mindmap) ;;; Code: @@ -1598,224 +1599,6 @@ Make sure that your smartphone is connected to the same WiFi network as this com "Switch to org-mode with `\\[eaf-edit-buffer-switch-to-org-mode]'. " )))) -(dbus-register-signal - :session "com.lazycat.eaf" "/com/lazycat/eaf" - "com.lazycat.eaf" "export_org_json" - #'eaf--export-org-json) - -(defun eaf--export-org-json (org-json-content org-file-path) - (let (org-parse-data) - (with-temp-buffer - (insert org-json-content) - (beginning-of-buffer) - (let* ((json (json-read)) - (root-node-name (cdr (assoc 'topic (assoc 'data json)))) - (children-node (cdr (assoc 'children (assoc 'data json))))) - ;; (message "%s" (org-json-decode (cdr (assoc 'data json)))) - (insert (org-json-decode (cdr (assoc 'data json)))) - (beginning-of-buffer) - (while (search-forward-regexp "\\*\\s-topic\\s-\"" nil t) - (let ((header-string (buffer-substring (save-excursion - (beginning-of-line) - (point)) - (save-excursion - (beginning-of-line) - (search-forward-regexp "\\*\\s-" nil t) - (point) - ))) - (content-string (buffer-substring (point) - (save-excursion - (end-of-line) - (backward-char 1) - (point))))) - (when (> (length header-string) 2) - (setq header-string (string-remove-prefix "*" header-string))) - (setq org-parse-data (concat org-parse-data (format "%s%s\n" header-string content-string))))) - - (with-temp-file org-file-path - (insert org-parse-data)) - )))) - -(defun json-read-r () - (let ((json-object-type 'alist)) - (let ((r (json-read))) - (if (listp r) (reverse r) r)))) - -(defun org-json-raw () - (let (p1) - (goto-char (point-min)) - (re-search-forward "[ \n\t]*") - (beginning-of-line) - (delete-region (point-min) (point)) - (if (re-search-forward "\\`#\\+begin_src" nil t) - ;; string - (progn - (if (re-search-forward "^#\\+end_src" nil t) - (progn (beginning-of-line) - (setq p1 (point))) - (setq p1 (point-max))) - (goto-char (point-min)) - (forward-line 1) - (buffer-substring-no-properties (point) p1)) - (goto-char (point-min)) - (json-read-r)))) - -(defun org-json-entry (str) - (let (lv header has-body p0 p1) - (with-temp-buffer - (insert str) - (goto-char (point-min)) - (end-of-line) - (setq header (buffer-substring (point-min) (point))) - ;; delete header - (delete-region (point-min) (point)) - ;; process header - (string-match "^\\(\\*+\\) +\\(.+?\\) *$" header) - (setq lv (length (match-string 1 header))) - ;; remove '*' - (setq header (match-string 2 header)) - (goto-char (point-min)) - (if (re-search-forward "\\`[ \n\t]*\\'" nil t) - (list lv header) ; body is empty - (list lv header (org-json-raw)))))) - -(defun org-json-entries () - (let (p0 pl) - ;; get all entries - (setq pl (let (ret tmp) - (goto-char (point-min)) - (while (re-search-forward "^\*+ " nil t) - (setq tmp (point)) - (beginning-of-line) - (setq ret (cons (point) ret)) - (goto-char tmp)) - (setq ret (cons (point-max) ret)) - (reverse ret))) - (setq p0 (car pl)) - (mapcar (lambda (p1) - (prog1 (org-json-entry - (buffer-substring-no-properties p0 p1)) - (setq p0 p1))) - (cdr pl)))) - -(defun org-json-split-header (lst &optional ret) - "Split header for the return of `org-json-entries'." - (if (null lst) (reverse ret) - (let (e0 e1 lst1) - (setq e0 (car lst)) - (setq lst1 (cdr lst)) - (setq e1 (if lst1 (car lst1) - '(0 "" ""))) - (if (>= (car e0) (car e1)) - ;; no child - (when (= (length e0) 2) - ;; split header - (if (string-match "^\\(.+?\\)[ \n\t]+\\(.+\\)$" (nth 1 e0)) - (setq e0 (list (nth 0 e0) - (match-string 1 (nth 1 e0)) - (with-temp-buffer - (insert (match-string 2 (nth 1 e0))) - (goto-char (point-min)) - (json-read-r)))) - (setq e0 (list (nth 0 e0) (nth 1 e0) :json-null)))) - (when (> (length e0) 2) - ;; drop unnecessary elem - (setq e0 (list (nth 0 e0) - (nth 1 e0))))) - (org-json-split-header lst1 (cons e0 ret))))) - -(defun org-json-gen-alist (lst) - "generate alist from return of `org-json-gen-alist', -actural call `org-json-gen-alist1' to work." - (cdr (org-json-gen-alist1 lst 1))) - -(defun org-json-gen-alist1 (lst lv &optional ret) - (if (or (null lst) - (< (car (car lst)) lv)) - ;; return list . ret - (cons lst (reverse ret)) - ;; not return - (let (e r1 kv) - ;; r1 is return of children - ;; kv is key-value pair - (setq e (car lst)) - (if (> (length e) 2) - ;; no child - (progn (setq kv (cons (nth 1 e) - (nth 2 e))) - (org-json-gen-alist1 (cdr lst) lv (cons kv ret))) - - (setq r1 (org-json-gen-alist1 (cdr lst) (1+ lv))) - ;; convert to array if necessray - (let ((seq (mapcar 'car (cdr r1)))) - (when (equal (mapcar 'number-to-string - (number-sequence 0 (1- (length seq)))) - seq) - (setq r1 (cons (car r1) - (vconcat (mapcar 'cdr (cdr r1))))))) - (setq kv (cons (nth 1 e) (cdr r1))) - (org-json-gen-alist1 (car r1) lv - (cons kv ret)))))) - - -(defun org-json-encode () - (save-excursion - (org-json-gen-alist - (org-json-split-header - (org-json-entries))))) - -(defun org-json-decode (obj &optional lv) - "Decode json object to org at level `lv'." - (unless lv (setq lv 1)) - (cond ((stringp obj) (if (string-match "\n\\'" obj) - ;; end with '\n' using #+begin_src block - (concat "#+begin_src\n" - obj - "#+end_src") - (concat "\"" - (replace-regexp-in-string - "\"" "\\\"" - (replace-regexp-in-string - "\\\\" "\\\\" obj)) - "\""))) - ((numberp obj) (number-to-string obj)) - ((vectorp obj) (if (= (length obj) 0) - "[]" - (let ((n 0) ns) - (mapconcat - (lambda (x) - (prog1 - (org-json-kv-decode - (cons (number-to-string n) - x) - lv) - (setq n (1+ n)))) - obj "\n")))) - ((equal obj json-null) "{}") - ((listp obj) (mapconcat - (lambda (x) - (org-json-kv-decode x lv)) - obj "\n")) - ((equal obj t) "true") - ((equal obj json-false) "false") - (t (error "org-json-decode type error: %S" obj)))) - -(defun org-json-kv-decode (kv lv) - "Decode a key-value pair." - (let ((k (car kv)) - (v (cdr kv)) - h ks vs) - (setq ks (cond ((symbolp k) (symbol-name k)) - ((stringp k) k) - ((numberp k) (number-to-string k)) - (t (error "org-json-kv-decode key type error: %S" k)))) - (setq h (concat (make-string lv ?*) " " ks)) - (setq vs (org-json-decode v (1+ lv))) - (if (string-match "\n" vs) - (concat h "\n" vs) - (concat h " " vs)) - )) - ;;;;;;;;;;;;;;;;;;;; Utils ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun eaf-get-view-info () (let* ((window-allocation (eaf-get-window-allocation (selected-window)))