Skip to content

Commit 209248f

Browse files
authored
Search for file popup (#50)
1 parent 32e3c11 commit 209248f

File tree

3 files changed

+203
-49
lines changed

3 files changed

+203
-49
lines changed

src/main/clojure/fominok/ideahelix/editor.clj

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
[fominok.ideahelix.editor.selection :refer :all]
1212
[fominok.ideahelix.editor.ui :as ui]
1313
[fominok.ideahelix.editor.util :refer [get-editor-height]]
14-
[fominok.ideahelix.keymap :refer [defkeymap]])
14+
[fominok.ideahelix.keymap :refer [defkeymap]]
15+
[fominok.ideahelix.search :refer :all])
1516
(:import
1617
(com.intellij.codeInsight.lookup
1718
LookupManager)
@@ -570,11 +571,8 @@
570571
(\f
571572
"File finder"
572573
[state project editor]
573-
(let [manager (.. SearchEverywhereManager (getInstance project))
574-
data-context (.getDataContext editor)
575-
action-event (AnActionEvent/createFromDataContext
576-
ActionPlaces/KEYBOARD_SHORTCUT nil data-context)]
577-
(.show manager "FileSearchEverywhereContributor" nil action-event)
574+
(do
575+
(search-file-name project editor)
578576
(assoc state :mode :normal)))
579577
(\r
580578
"Rename symbol"
@@ -636,51 +634,51 @@
636634

637635

638636
(:match
639-
(\i
640-
[state] (assoc state :mode :match-inside))
641-
(\a
642-
[state] (assoc state :mode :match-around)))
637+
(\i
638+
[state] (assoc state :mode :match-inside))
639+
(\a
640+
[state] (assoc state :mode :match-around)))
643641

644642
(:select-match
645-
(\i
646-
[state] (assoc state :mode :select-match-inside))
647-
(\a
648-
[state] (assoc state :mode :select-match-around)))
643+
(\i
644+
[state] (assoc state :mode :select-match-inside))
645+
(\a
646+
[state] (assoc state :mode :select-match-around)))
649647

650648
(:match-inside
651-
(_
652-
"Select inside"
653-
[project state document caret char]
654-
(-> (ihx-selection document caret)
655-
(ihx-select-inside document char)
656-
(ihx-apply-selection! document))
657-
[state] (assoc state :mode :normal)))
649+
(_
650+
"Select inside"
651+
[project state document caret char]
652+
(-> (ihx-selection document caret)
653+
(ihx-select-inside document char)
654+
(ihx-apply-selection! document))
655+
[state] (assoc state :mode :normal)))
658656

659657
(:select-match-inside
660-
(_
661-
"Select inside"
662-
[project state document caret char]
663-
(-> (ihx-selection document caret)
664-
(ihx-select-inside document char)
665-
(ihx-apply-selection! document))
666-
[state] (assoc state :mode :select)))
658+
(_
659+
"Select inside"
660+
[project state document caret char]
661+
(-> (ihx-selection document caret)
662+
(ihx-select-inside document char)
663+
(ihx-apply-selection! document))
664+
[state] (assoc state :mode :select)))
667665

668666
(:match-around
669-
(_
670-
"Select around"
671-
[project state document caret char]
672-
(-> (ihx-selection document caret)
673-
(ihx-select-around document char)
674-
(ihx-apply-selection! document))
675-
[state] (assoc state :mode :normal)))
667+
(_
668+
"Select around"
669+
[project state document caret char]
670+
(-> (ihx-selection document caret)
671+
(ihx-select-around document char)
672+
(ihx-apply-selection! document))
673+
[state] (assoc state :mode :normal)))
676674

677675
(:select-match-around
678-
(_
679-
"Select around"
680-
[project state document caret char]
681-
(-> (ihx-selection document caret)
682-
(ihx-select-around document char)
683-
(ihx-apply-selection! document))))
676+
(_
677+
"Select around"
678+
[project state document caret char]
679+
(-> (ihx-selection document caret)
680+
(ihx-select-around document char)
681+
(ihx-apply-selection! document))))
684682

685683
((:or :match :select-match)
686684
(\s

src/main/clojure/fominok/ideahelix/editor/selection.clj

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@
533533
(= (:direction match-info) :open) {:open-char char :close-char (:match match-info)}
534534
:else {:open-char (:match match-info) :close-char char})))
535535

536+
536537
(defn find-matches
537538
[{:keys [_ offset]} document char]
538539
(let [{:keys [open-char close-char]} (get-open-close-chars char)
@@ -548,12 +549,14 @@
548549
(= close-char curr-char) {:left (previous-match text (dec offset) close-char open-char)
549550
:right offset}))))
550551

552+
551553
(defn ihx-select-inside
552554
[selection document char]
553555
(let [matches (find-matches selection document char)]
554556
(when (not (nil? matches))
555557
(assoc selection :offset (inc (:left matches)) :anchor (dec (:right matches))))))
556558

559+
557560
(defn ihx-select-around
558561
[selection document char]
559562
(let [matches (find-matches selection document char)]
@@ -565,14 +568,14 @@
565568
[{:keys [offset anchor] :as selection} document char]
566569
(when (printable-char? char)
567570
(let [{:keys [open-char close-char]} (get-open-close-chars char)]
568-
(cond (> offset anchor)
569-
(do (.insertString document (inc offset) (str close-char))
570-
(.insertString document anchor (str open-char))
571-
(assoc selection :offset (+ 2 offset) :anchor anchor))
572-
:else
573-
(do (.insertString document (inc anchor) (str close-char))
574-
(.insertString document offset (str open-char))
575-
(assoc selection :offset offset :anchor (+ 2 anchor)))))))
571+
(cond (> offset anchor)
572+
(do (.insertString document (inc offset) (str close-char))
573+
(.insertString document anchor (str open-char))
574+
(assoc selection :offset (+ 2 offset) :anchor anchor))
575+
:else
576+
(do (.insertString document (inc anchor) (str close-char))
577+
(.insertString document offset (str open-char))
578+
(assoc selection :offset offset :anchor (+ 2 anchor)))))))
576579

577580

578581
(defn ihx-surround-delete
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
(ns fominok.ideahelix.search
2+
(:import
3+
(com.intellij.openapi.application
4+
ModalityState
5+
ReadAction)
6+
(com.intellij.openapi.editor
7+
Editor)
8+
(com.intellij.openapi.fileEditor
9+
FileEditorManager)
10+
(com.intellij.openapi.project
11+
Project
12+
ProjectUtil
13+
ProjectUtilCore)
14+
(com.intellij.openapi.ui.popup
15+
JBPopupFactory)
16+
(com.intellij.psi.codeStyle
17+
NameUtil)
18+
(com.intellij.psi.search
19+
FilenameIndex
20+
GlobalSearchScope)
21+
(com.intellij.ui.components
22+
JBList
23+
JBScrollPane)
24+
(com.intellij.util
25+
Alarm
26+
Alarm$ThreadToUse)
27+
(com.intellij.util.concurrency
28+
AppExecutorUtil)
29+
(java.awt
30+
BorderLayout
31+
Dimension)
32+
(java.awt.event
33+
ActionEvent)
34+
(javax.swing
35+
AbstractAction
36+
DefaultListModel
37+
JPanel
38+
JTextField
39+
KeyStroke
40+
ListSelectionModel)
41+
(javax.swing.event
42+
DocumentListener)))
43+
44+
45+
(defn filter-list
46+
[alarm ^JTextField input ^JBList list ^DefaultListModel model files]
47+
(.cancelAllRequests alarm)
48+
(.addRequest
49+
alarm
50+
(fn []
51+
(let [query (.trim (.getText input))
52+
matcher (.. (NameUtil/buildMatcher (str "*" query)) build)
53+
scored-items (map (fn [[path _]]
54+
{:score (.matchingDegree matcher path)
55+
:path path})
56+
files)
57+
items
58+
(->> scored-items
59+
(sort-by :score >)
60+
(take 20)
61+
(map :path))]
62+
63+
(.clear model)
64+
(doseq [item items]
65+
(.addElement model item))
66+
(when-not (empty? items)
67+
(.setSelectedIndex list 0))))
68+
100
69+
true))
70+
71+
72+
(defn relativize-path
73+
[project path]
74+
(let [base-path (.getPath (ProjectUtil/guessProjectDir project))]
75+
(if (and (.startsWith path base-path) (not= path base-path))
76+
(.substring path (inc (count base-path)))
77+
path)))
78+
79+
80+
(defn get-filenames!
81+
[project result]
82+
(.. (^[Callable] ReadAction/nonBlocking
83+
(fn []
84+
(into {} (keep (fn [name]
85+
(when-let [file (first (FilenameIndex/getVirtualFilesByName name (GlobalSearchScope/projectScope project)))]
86+
[(relativize-path project (.getPath file)) file]))
87+
(FilenameIndex/getAllFilenames project)))))
88+
(finishOnUiThread
89+
(ModalityState/any)
90+
#(vreset! result %))
91+
(submit (AppExecutorUtil/getAppExecutorService))))
92+
93+
94+
(defn search-file-name
95+
[project ^Editor parent]
96+
(let [files (volatile! {})
97+
alarm (Alarm. Alarm$ThreadToUse/POOLED_THREAD project)
98+
model (DefaultListModel.)
99+
list (doto (JBList. model)
100+
(.setSelectionMode ListSelectionModel/SINGLE_SELECTION)
101+
(.setSelectedIndex 0))
102+
input (JTextField.)
103+
panel (doto (JPanel. (BorderLayout. 0 5))
104+
(.add input BorderLayout/NORTH)
105+
(.add (JBScrollPane. list) BorderLayout/CENTER)
106+
(.setPreferredSize (Dimension. 600 400)))
107+
popup (-> (JBPopupFactory/getInstance)
108+
(.createComponentPopupBuilder panel input)
109+
(.setRequestFocus true)
110+
(.setTitle "Find File")
111+
(.setMovable true)
112+
(.setResizable true)
113+
(.createPopup))]
114+
115+
(get-filenames! project files)
116+
117+
(doto (.getInputMap input)
118+
(.put (KeyStroke/getKeyStroke "control N") "selectNext")
119+
(.put (KeyStroke/getKeyStroke "control P") "selectPrevious"))
120+
(doto (.getActionMap input)
121+
(.put "selectNext"
122+
(proxy [AbstractAction] []
123+
(actionPerformed
124+
[^ActionEvent _]
125+
(let [i (min (inc (.getSelectedIndex list)) (dec (.. list (getModel) (getSize))))]
126+
(.setSelectedIndex list i)
127+
(.ensureIndexIsVisible list i)))))
128+
(.put "selectPrevious"
129+
(proxy [AbstractAction] []
130+
(actionPerformed
131+
[^ActionEvent _]
132+
(let [i (max (dec (.getSelectedIndex list)) 0)]
133+
(.setSelectedIndex list i)
134+
(.ensureIndexIsVisible list i))))))
135+
136+
(.addActionListener input
137+
(proxy [java.awt.event.ActionListener] []
138+
(actionPerformed
139+
[^ActionEvent _]
140+
(let [selected (.getSelectedValue list)]
141+
(.cancel popup)
142+
(when-let [file (get @files selected)]
143+
(.openFile (FileEditorManager/getInstance project) file true))))))
144+
145+
(.addDocumentListener (.getDocument input)
146+
(proxy [DocumentListener] []
147+
(insertUpdate [_] (filter-list alarm input list model @files))
148+
149+
(removeUpdate [_] (filter-list alarm input list model @files))
150+
151+
(changedUpdate [_] nil)))
152+
153+
(.showInCenterOf popup (.getContentComponent parent))))

0 commit comments

Comments
 (0)