mirror of https://github.com/logseq/logseq
Auto pairs
parent
6141d66182
commit
a9f5aa045e
|
@ -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"]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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?]
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue