Auto pairs

pull/645/head
Tienson Qin 2020-05-29 13:57:01 +08:00
parent 6141d66182
commit a9f5aa045e
5 changed files with 134 additions and 29 deletions

View File

@ -2,7 +2,8 @@
(:require [frontend.util :as util] (:require [frontend.util :as util]
[frontend.state :as state] [frontend.state :as state]
[clojure.string :as string] [clojure.string :as string]
[goog.dom :as gdom])) [goog.dom :as gdom]
[goog.object :as gobj]))
(defonce *show-commands (atom false)) (defonce *show-commands (atom false))
(defonce *slash-caret-pos (atom nil)) (defonce *slash-caret-pos (atom nil))
@ -69,8 +70,8 @@
{:keys [last-pattern postfix-fn backward-pos forward-pos] {:keys [last-pattern postfix-fn backward-pos forward-pos]
:or {last-pattern "/"} :or {last-pattern "/"}
:as option}] :as option}]
(let [edit-content (state/get-edit-content id) (let [input (gdom/getElement id)
input (gdom/getElement id) edit-content (gobj/get input "value")
current-pos (:pos (util/get-caret-pos input)) current-pos (:pos (util/get-caret-pos input))
prefix (subs edit-content 0 current-pos) prefix (subs edit-content 0 current-pos)
@ -89,6 +90,38 @@
new-pos new-pos
(+ new-pos 1))))) (+ new-pos 1)))))
(defn simple-insert!
[id value
{:keys [backward-pos forward-pos check-fn]
:as option}]
(let [input (gdom/getElement id)
edit-content (gobj/get input "value")
current-pos (:pos (util/get-caret-pos input))
prefix (subs edit-content 0 current-pos)
new-value (str prefix
value
(subs edit-content current-pos))
new-pos (- (+ (count prefix)
(count value)
(or forward-pos 0))
(or backward-pos 0))]
(state/set-heading-content-and-last-pos! id new-value new-pos)
(util/move-cursor-to input new-pos)
(when check-fn
(check-fn new-value (dec (count prefix))))))
(defn delete-pair!
[id]
(let [input (gdom/getElement id)
edit-content (gobj/get input "value")
current-pos (:pos (util/get-caret-pos input))
prefix (subs edit-content 0 (dec current-pos))
new-value (str prefix
(subs edit-content (inc current-pos)))
new-pos (count prefix)]
(state/set-heading-content-and-last-pos! id new-value new-pos)
(util/move-cursor-to input new-pos)))
(defn get-matched-commands (defn get-matched-commands
[text] [text]
(filter (filter
@ -128,7 +161,7 @@
(defmethod handle-step :editor/clear-current-slash [[_]] (defmethod handle-step :editor/clear-current-slash [[_]]
(when-let [input-id (state/get-edit-input-id)] (when-let [input-id (state/get-edit-input-id)]
(when-let [current-input (gdom/getElement input-id)] (when-let [current-input (gdom/getElement input-id)]
(let [edit-content (state/get-edit-content input-id) (let [edit-content (gobj/get current-input "value")
current-pos (:pos (util/get-caret-pos current-input)) current-pos (:pos (util/get-caret-pos current-input))
prefix (subs edit-content 0 current-pos) prefix (subs edit-content 0 current-pos)
prefix (util/replace-last "/" prefix "") prefix (util/replace-last "/" prefix "")
@ -144,7 +177,7 @@
(defmethod handle-step :editor/set-marker [[_ marker] format] (defmethod handle-step :editor/set-marker [[_ marker] format]
(when-let [input-id (state/get-edit-input-id)] (when-let [input-id (state/get-edit-input-id)]
(when-let [current-input (gdom/getElement input-id)] (when-let [current-input (gdom/getElement input-id)]
(let [edit-content (state/get-edit-content input-id) (let [edit-content (gobj/get current-input "value")
slash-pos (:pos @*slash-caret-pos) slash-pos (:pos @*slash-caret-pos)
[re-pattern new-line-re-pattern] (if (= :org format) [re-pattern new-line-re-pattern] (if (= :org format)
[#"\*+\s" #"\n\*+\s"] [#"\*+\s" #"\n\*+\s"]

View File

@ -53,6 +53,39 @@
(when restore? (when restore?
(commands/restore-state restore?))) (commands/restore-state restore?)))
(def autopair-map
{"[" "]"
"{" "}"
"(" ")"})
(defn- autopair
[input-id prefix format {:keys [restore?]
:or {restore? true}
:as option}]
(let [value (get autopair-map prefix)
value (str prefix value)
input (gdom/getElement input-id)]
(when value
(let [[prefix pos] (commands/simple-insert! input-id value
{:backward-pos 1
:check-fn (fn [new-value prefix-pos]
(when (>= prefix-pos 0)
[(subs new-value prefix-pos (+ prefix-pos 2))
(+ prefix-pos 2)]))})]
(case prefix
"[["
(do
(commands/handle-step [:editor/search-page])
(reset! commands/*slash-caret-pos (util/get-caret-pos input)))
"(("
(do
(commands/handle-step [:editor/search-block])
(reset! commands/*slash-caret-pos (util/get-caret-pos input)))
nil))
)))
(defn- upload-image (defn- upload-image
[id files format uploading? drop?] [id files format uploading? drop?]
(image/upload (image/upload
@ -288,8 +321,7 @@
(defn on-backspace (defn on-backspace
[state e] [state e]
(let [{:keys [id heading-id heading-parent-id dummy? value pos format]} (get-state state) (let [{:keys [id heading-id heading-parent-id dummy? value pos format]} (get-state state)]
edit-content (state/get-edit-content id)]
(when (and heading-id (= value "")) (when (and heading-id (= value ""))
(if @*should-delete? (if @*should-delete?
(do (do
@ -443,7 +475,8 @@
(mixins/keyboard-mixin "alt+shift+right" #(adjust-heading-level! % :right) edit-heading? get-input) (mixins/keyboard-mixin "alt+shift+right" #(adjust-heading-level! % :right) edit-heading? get-input)
(mixins/event-mixin (mixins/event-mixin
(fn [state] (fn [state]
(let [input-id (last (:rum/args state)) (let [{:keys [id format]} (get-state state)
input-id id
input (gdom/getElement input-id)] input (gdom/getElement input-id)]
(let [{:keys [format heading]} (get-state state)] (let [{:keys [format heading]} (get-state state)]
(mixins/hide-when-esc-or-outside (mixins/hide-when-esc-or-outside
@ -475,16 +508,53 @@
8 (fn [state e] 8 (fn [state e]
(let [node (gdom/getElement input-id) (let [node (gdom/getElement input-id)
current-pos (:pos (util/get-caret-pos node)) current-pos (:pos (util/get-caret-pos node))
value (gobj/get node "value")] value (gobj/get node "value")
(when (and (> current-pos 1) deleted (and (> current-pos 0)
(= (nth value (dec current-pos)) "/")) (nth value (dec current-pos)))]
(reset! *slash-caret-pos nil) (cond
(reset! *show-commands false)))) (and (> current-pos 1)
(= (nth value (dec current-pos)) "/"))
(do
(reset! *slash-caret-pos nil)
(reset! *show-commands false))
;; pair
(and
deleted
(contains?
(set (keys autopair-map))
deleted)
(>= (count value) (inc current-pos))
(= (nth value current-pos)
(get autopair-map deleted)))
(do
(util/stop e)
(commands/delete-pair! id)
(reset! *should-delete? false))
:else
nil)))
;; tab ;; tab
9 (fn [state e] 9 (fn [state e]
(when-not (state/get-editor-show-input) (when-not (state/get-editor-show-input)
(util/stop e) (util/stop e)
(adjust-heading-level! state nil))) (adjust-heading-level! state nil)))
;; autopairs
;; [ && { (shift+219)
219 (fn [state e]
(util/stop e)
(autopair input-id (gobj/get e "key") format nil)
(when (and (not (gobj/get e "shiftKey"))
;; double `[]`
)
;; show page
)
)
;; (
57 (fn [state e]
(util/stop e)
(autopair input-id "(" format nil))
} }
(fn [e key-code] (fn [e key-code]
;; (swap! state/state assoc ;; (swap! state/state assoc
@ -498,6 +568,7 @@
(when-let [matched-commands (seq (get-matched-commands input))] (when-let [matched-commands (seq (get-matched-commands input))]
(reset! *slash-caret-pos (util/get-caret-pos input)) (reset! *slash-caret-pos (util/get-caret-pos input))
(reset! *show-commands true))) (reset! *show-commands true)))
;; backspace ;; backspace
8 on-backspace} 8 on-backspace}
(fn [e key-code] (fn [e key-code]
@ -520,9 +591,9 @@
(reset! *show-commands false) (reset! *show-commands false)
))))))))) )))))))))
{:after (fn [state _props] {:after (fn [state _props]
(let [[content {:keys [dummy? heading heading-id]} id] (:rum/args state)] (let [[content {:keys [dummy? heading heading-id]} id] (:rum/args state)]
(reset! *should-delete? false)) (reset! *should-delete? false))
state) state)
:did-mount (fn [state] :did-mount (fn [state]
(let [[content {:keys [heading format dummy? format]} id] (:rum/args state)] (let [[content {:keys [heading format dummy? format]} id] (:rum/args state)]
(let [content (handler/remove-level-spaces content format)] (let [content (handler/remove-level-spaces content format)]
@ -553,11 +624,11 @@
:else :else
(let [cache [(:heading/uuid heading) value]] (let [cache [(:heading/uuid heading) value]]
(when (not= @*last-edit-heading cache) (when (not= @*last-edit-heading cache)
(when-not (string/blank? value) (when-not (string/blank? value)
(when (not= (string/trim new-value) (when (not= (string/trim new-value)
(string/trim (:heading/content heading))) (string/trim (:heading/content heading)))
(handler/save-heading-if-changed! heading new-value)) (handler/save-heading-if-changed! heading new-value))
(reset! *last-edit-heading cache))))))) (reset! *last-edit-heading cache)))))))
(clear-when-saved!)) (clear-when-saved!))
state)} state)}
[content {:keys [on-hide dummy? node format heading] [content {:keys [on-hide dummy? node format heading]

View File

@ -10,7 +10,9 @@
[frontend.format :as format] [frontend.format :as format]
[frontend.components.content :as content] [frontend.components.content :as content]
[frontend.config :as config] [frontend.config :as config]
[frontend.utf8 :as utf8])) [frontend.utf8 :as utf8]
[goog.dom :as gdom]
[goog.object :as gobj]))
(defn- get-path (defn- get-path
[state] [state]
@ -39,7 +41,9 @@
save-file-handler (fn [content] save-file-handler (fn [content]
(fn [_] (fn [_]
(when (handler/file-changed? encoded-path content) (when (handler/file-changed? encoded-path content)
(handler/alter-file (state/get-current-repo) path (state/get-edit-content encoded-path) nil)))) (let [new-content (-> (gdom/getElement encoded-path)
(gobj/get "value"))]
(handler/alter-file (state/get-current-repo) path new-content nil)))))
edit-raw-handler (fn [] edit-raw-handler (fn []
(let [content (db/get-file path)] (let [content (db/get-file path)]
(content/content encoded-path {:content content (content/content encoded-path {:content content

View File

@ -461,8 +461,9 @@
(defn file-changed? (defn file-changed?
[input-id content] [input-id content]
(not= (string/trim content) (when-let [input (gdom/getElement input-id)]
(string/trim (state/get-edit-content input-id)))) (not= (string/trim content)
(string/trim (gobj/get input "value")))))
(defn alter-file (defn alter-file
[repo path content {:keys [reset?] [repo path content {:keys [reset?]

View File

@ -115,10 +115,6 @@
[] []
(:edit-heading @state)) (:edit-heading @state))
(defn get-edit-content
[input-id]
(get-in @state [:editor/content input-id]))
(defn set-edit-content! (defn set-edit-content!
[input-id value set-input-value?] [input-id value set-input-value?]
(when input-id (when input-id