| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 | 
							- (ns frontend.util.drawer
 
-   (:require [clojure.string :as string]
 
-             [frontend.util :as util]
 
-             [frontend.util.property :as property]
 
-             [frontend.format.mldoc :as mldoc]))
 
- (defn drawer-start
 
-   [typ]
 
-   (util/format ":%s:" (string/upper-case typ)))
 
- (defonce drawer-end ":END:")
 
- (defonce logbook-start ":LOGBOOK:")
 
- (defn build-drawer-str
 
-   ([typ]
 
-    (build-drawer-str typ nil))
 
-   ([typ value]
 
-    (if value
 
-      (string/join "\n" [(drawer-start typ) value drawer-end])
 
-      (string/join "\n" [(drawer-start typ) drawer-end]))))
 
- (defn get-drawer-ast
 
-   [format content typ]
 
-   (let [ast (mldoc/->edn content (mldoc/default-config format))
 
-         typ-drawer (ffirst (filter (fn [x]
 
-                                      (mldoc/typ-drawer? x typ)) ast))]
 
-     typ-drawer))
 
- (defn insert-drawer
 
-   [format content typ value]
 
-   (when (string? content)
 
-     (try
 
-       (let [ast (mldoc/->edn content (mldoc/default-config format))
 
-             has-properties? (some (fn [x] (mldoc/properties? x)) ast)
 
-             has-typ-drawer? (some (fn [x] (mldoc/typ-drawer? x typ)) ast)
 
-             lines (string/split-lines content)
 
-             title (first lines)
 
-             body (rest lines)
 
-             scheduled (filter #(string/starts-with? % "SCHEDULED") lines)
 
-             deadline (filter #(string/starts-with? % "DEADLINE") lines)
 
-             body-without-timestamps (vec
 
-                                      (filter
 
-                                       #(not (or (string/starts-with? % "SCHEDULED")
 
-                                                 (string/starts-with? % "DEADLINE")))
 
-                                       body))
 
-             start-idx (.indexOf body-without-timestamps (drawer-start typ))
 
-             end-idx (let [[before after] (split-at start-idx body-without-timestamps)]
 
-                       (+ (count before) (.indexOf after drawer-end)))
 
-             result  (cond
 
-                       (not has-typ-drawer?)
 
-                       (let [drawer (build-drawer-str typ value)]
 
-                         (if has-properties?
 
-                           (cond
 
-                             (= :org format)
 
-                             (let [prop-start-idx (.indexOf body-without-timestamps property/properties-start)
 
-                                   prop-end-idx (.indexOf body-without-timestamps property/properties-end)
 
-                                   properties (subvec body-without-timestamps prop-start-idx (inc prop-end-idx))
 
-                                   after (subvec body-without-timestamps (inc prop-end-idx))]
 
-                               (string/join "\n" (concat [title] scheduled deadline properties [drawer] after)))
 
-                             :else
 
-                             (let [properties-count (count (second (first (second ast))))
 
-                                   properties (subvec body-without-timestamps 0 properties-count)
 
-                                   after (subvec body-without-timestamps properties-count)]
 
-                               (string/join "\n" (concat [title] scheduled deadline properties [drawer] after))))
 
-                           (string/join "\n" (concat [title] scheduled deadline [drawer] body-without-timestamps))))
 
-                       (and has-typ-drawer?
 
-                            (>= start-idx 0) (> end-idx 0) (> end-idx start-idx))
 
-                       (let [before (subvec body-without-timestamps 0 start-idx)
 
-                             middle (conj
 
-                                     (subvec body-without-timestamps (inc start-idx) end-idx)
 
-                                     value)
 
-                             after (subvec body-without-timestamps (inc end-idx))
 
-                             lines (concat [title] scheduled deadline before
 
-                                           [(drawer-start typ)] middle [drawer-end] after)]
 
-                         (string/join "\n" lines))
 
-                       :else
 
-                       content)]
 
-         (string/trimr result))
 
-       (catch js/Error e
 
-         (js/console.error e)
 
-         content))))
 
- (defn contains-logbook?
 
-   [content]
 
-   (and (util/safe-re-find (re-pattern (str "(?i)" logbook-start)) content)
 
-        (util/safe-re-find (re-pattern (str "(?i)" drawer-end)) content)))
 
- ;; TODO: DRY
 
- (defn remove-logbook
 
-   [content]
 
-   (if (contains-logbook? content)
 
-     (let [lines (string/split-lines content)
 
-           [title-lines body] (split-with (fn [l]
 
-                                            (not (string/starts-with? (string/upper-case (string/triml l)) ":LOGBOOK:")))
 
-                                          lines)
 
-           body (drop-while (fn [l]
 
-                              (let [l' (string/lower-case (string/trim l))]
 
-                                (or
 
-                                 (not (string/starts-with? l' ":end:"))
 
-                                 (string/blank? l))))
 
-                            body)
 
-           body (if (and (seq body)
 
-                         (string/starts-with? (string/lower-case (string/triml (first body))) ":end:"))
 
-                  (let [line (string/replace (first body) #"(?i):end:\s?" "")]
 
-                    (if (string/blank? line)
 
-                      (rest body)
 
-                      (cons line (rest body))))
 
-                  body)]
 
-       (->> (concat title-lines body)
 
-            (string/join "\n")))
 
-     content))
 
- (defn get-logbook
 
-   [body]
 
-   (-> (filter (fn [v] (and (vector? v)
 
-                           (= (first v) "Drawer")
 
-                           (= (second v) "logbook"))) body)
 
-       first))
 
- (defn with-logbook
 
-   [block content]
 
-   (let [new-clocks (last (get-drawer-ast (:block/format block) content "logbook"))
 
-         logbook (get-logbook (:block/body block))]
 
-     (if logbook
 
-       (let [content (remove-logbook content)
 
-             clocks (->> (concat new-clocks (when-not new-clocks (last logbook)))
 
-                         (distinct))
 
-             clocks (->> (map string/trim clocks)
 
-                         (remove string/blank?)
 
-                         (string/join "\n"))]
 
-         (if (:block/title block)
 
-           (insert-drawer (:block/format block) content "LOGBOOK" clocks)
 
-           content))
 
-       content)))
 
 
  |