-
Notifications
You must be signed in to change notification settings - Fork 21
/
snippet-manager.coffee
209 lines (159 loc) · 6.28 KB
/
snippet-manager.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
{LTool,get_tex_root} = require './ltutils'
module.exports =
class SnippetManager extends LTool
snippetService: null
constructor: ->
super
console.log("Created SnippetManager")
setService: (service) ->
console.log("Set snippet service")
console.log(service)
@snippetService = service
wrapInCommand: ->
# In case we haven't gotten the snippets service yet
unless @snippetService?
atom.notifications.addInfo(
"Still waiting for the snippets service to activate..."
)
return
te = atom.workspace.getActiveTextEditor()
range = te.getSelectedBufferRange()
text = te.getTextInBufferRange(range)
text = text.replace(/\\/g, "\\\\")
te.transact =>
te.setTextInBufferRange(range, "")
snippet = "\\\\$1cmd\\{#{text}\\}"
# This is a HACK around current snippet limitations
# Also note that we cannot trigger jumping to the end with $0
cmd_range = [[range.start.row, range.start.column+1], [range.start.row, range.start.column+4]]
@snippetService.insertSnippet(snippet)
te.setSelectedBufferRange(cmd_range)
wrapInEnvironment: ->
# In case we haven't gotten the snippets service yet
unless @snippetService?
atom.notifications.addInfo(
"Still waiting for the snippets service to activate..."
)
return
te = atom.workspace.getActiveTextEditor()
range = te.getSelectedBufferRange()
text = te.getTextInBufferRange(range)
text = text.replace(/\\/g, "\\\\")
te.transact =>
te.setTextInBufferRange(range, "")
snippet = "\\\\begin\{$1env\}\n#{text}\n\\\\end\{$1env\}"
# This is a HACK around current snippet limitations
cmd_range_begin = [[range.start.row, range.start.column+7], [range.start.row, range.start.column+10]]
nlines = text.split('\n').length
cmd_range_end = [[range.start.row+nlines+1, range.start.column+5], [range.start.row+nlines+1, range.start.column+8]]
@snippetService.insertSnippet(snippet)
te.setSelectedBufferRange(cmd_range_begin)
te.addSelectionForBufferRange(cmd_range_end)
insertCmdEnv: (what) ->
max_length = 100 # Maximum length of LaTeX command (should be enough!)
unless @snippetService?
atom.notifications.addInfo(
"Still waiting for the snippets service to activate..."
)
return
te = atom.workspace.getActiveTextEditor()
# Using Atom's API:
te.selectToBeginningOfWord()
range = te.getSelectedBufferRange()
arg = te.getTextInBufferRange(range)
te.setSelectedBufferRange(range, '')
if arg
snippet = switch what
when "command"
"\\\\#{arg}\\{$1\\}$0"
when "environment"
"\\\\begin\{#{arg}\}\n$1\n\\\\end\{#{arg}\}$0"
@snippetService.insertSnippet(snippet)
wrapIn: (cmd) ->
unless @snippetService?
atom.notifications.addInfo(
"Still waiting for the snippets service to activate..."
)
return
te = atom.workspace.getActiveTextEditor()
range = te.getSelectedBufferRange()
text = te.getTextInBufferRange(range)
text = text.replace(/\\/g, "\\\\")
# Use snippets to easily remove selection, move cursor at end
# (but only if there is some text)
if text
snippet = "\\\\#{cmd}\\{#{text}\\}$0"
else
snippet = "\\\\#{cmd}\\{$1\\}$0"
@snippetService.insertSnippet(snippet)
closeEnvironment: ->
begin_rx = /\\(begin|end)\{([^\}]*)\}/
te = atom.workspace.getActiveTextEditor()
cursor = te.getCursorBufferPosition()
found = false
# TODO make this smarter: look for UNOPENED environments from beginning
# NOTE: remember that the callback param is an OBJECT!
te.backwardsScanInBufferRange begin_rx, [[0,0],cursor], ({match, matchText, range, stop, replace}) =>
console.log(match)
console.log(stop)
# We only process one match, the first
if match[1] == 'begin'
te.insertText("\\end{#{match[2]}}\n")
found = true
# otherwise, match[1] == 'end', and we do nothing
# When we first match, stop, so we don't get any further matches
stop()
if !found
atom.notifications.addError "Could not find unmatched \\begin"
# Handle dollar-sign matching
# If there is a $ *after* the cursor, just move past it.
# If there is no $ after, and no $ before, add $[cursor]$
# Sane $$...$$ handling
# Add space between $ $ so highlighting doesn't go crazy
# Also handle selectioj
dollarSign: ->
te = atom.workspace.getActiveTextEditor()
# First, check if there is a selection, and if so, add $..$ around it
if text = te.getSelectedText()
text = text.replace(/\\/g, "\\\\")
range = te.getSelectedBufferRange()
te.setSelectedBufferRange(range, '')
@snippetService.insertSnippet("\$#{text}\$")
return
cursor = te.getCursorBufferPosition()
text = te.getTextInBufferRange([[cursor.row,0],[cursor.row,cursor.column+1]])
pos = cursor.column
# if cursor followed by $ or $$, skip themm
if text[pos]? && text[pos] == '$'
te.moveRight()
if text[pos+1]? && text[pos+1] == '$'
te.moveRight()
return
# Here cursor is NOT followed by $. Then insert as needed
if (pos==0) || (pos>0) && !text[pos-1].match(/[a-zA-Z0-9\$\\]/)
snippet = "\$${1: }\$"
@snippetService.insertSnippet(snippet)
#te.addSelectionForBufferRange([[cursor.row,pos+1],[cursor.row, pos+2]])
else
te.insertText('$')
# Add matched quotes
quotes: (left, right, ch) ->
te = atom.workspace.getActiveTextEditor()
# First, check if there is a selection, and if so, add quotes around it
if text = te.getSelectedText()
text = text.replace(/\\/g, "\\\\")
range = te.getSelectedBufferRange()
te.setSelectedBufferRange(range, '')
# Use snippet to leave selection on (same as ST)
@snippetService.insertSnippet("#{left}${1:#{text}}#{right}")
return
# Ensure there is no character preceding the quote
cursor = te.getCursorBufferPosition()
text = te.getTextInBufferRange([[cursor.row,0],[cursor.row,cursor.column]])
if text[cursor.column-1]? and
!text[cursor.column-1].match(/\s/) and
text[cursor.column-1] != left
te.insertText(ch)
return
snippet = "#{left}$0#{right}"
@snippetService.insertSnippet(snippet)