Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit 737bd9c

Browse files
committed
Convert whitespace package source to JS
1 parent ad6b1ee commit 737bd9c

File tree

6 files changed

+265
-132
lines changed

6 files changed

+265
-132
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules
2+
npm-debug.log

lib/main.coffee

-9
This file was deleted.

lib/main.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** @babel */
2+
3+
import Whitespace from './whitespace'
4+
5+
export default {
6+
activate () {
7+
this.whitespace = new Whitespace()
8+
},
9+
10+
deactivate () {
11+
if (this.whitespace) this.whitespace.destroy()
12+
this.whitespace = null
13+
}
14+
}

lib/whitespace.coffee

-123
This file was deleted.

lib/whitespace.js

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/** @babel */
2+
3+
import {CompositeDisposable} from 'atom'
4+
5+
export default class Whitespace {
6+
constructor () {
7+
this.subscriptions = new CompositeDisposable()
8+
9+
this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
10+
return this.handleEvents(editor)
11+
}))
12+
13+
this.subscriptions.add(atom.commands.add('atom-workspace', {
14+
'whitespace:remove-trailing-whitespace': () => {
15+
let editor = atom.workspace.getActiveTextEditor()
16+
17+
if (editor) {
18+
this.removeTrailingWhitespace(editor, editor.getGrammar().scopeName)
19+
}
20+
},
21+
22+
'whitespace:save-with-trailing-whitespace': () => {
23+
let editor = atom.workspace.getActiveTextEditor()
24+
25+
if (editor) {
26+
this.ignore = true
27+
editor.save()
28+
this.ignore = false
29+
}
30+
},
31+
32+
'whitespace:save-without-trailing-whitespace': () => {
33+
let editor = atom.workspace.getActiveTextEditor()
34+
35+
if (editor) {
36+
this.removeTrailingWhitespace(editor, editor.getGrammar().scopeName)
37+
editor.save()
38+
}
39+
},
40+
41+
'whitespace:convert-tabs-to-spaces': () => {
42+
let editor = atom.workspace.getActiveTextEditor()
43+
44+
if (editor) {
45+
this.convertTabsToSpaces(editor)
46+
}
47+
},
48+
49+
'whitespace:convert-spaces-to-tabs': () => {
50+
let editor = atom.workspace.getActiveTextEditor()
51+
52+
if (editor) {
53+
return this.convertSpacesToTabs(editor)
54+
}
55+
},
56+
57+
'whitespace:convert-all-tabs-to-spaces': () => {
58+
let editor = atom.workspace.getActiveTextEditor()
59+
60+
if (editor) {
61+
return this.convertTabsToSpaces(editor, true)
62+
}
63+
}
64+
}))
65+
}
66+
67+
destroy () {
68+
return this.subscriptions.dispose()
69+
}
70+
71+
handleEvents (editor) {
72+
let buffer = editor.getBuffer()
73+
74+
let bufferSavedSubscription = buffer.onWillSave(() => {
75+
return buffer.transact(() => {
76+
let scopeDescriptor = editor.getRootScopeDescriptor()
77+
78+
if (atom.config.get('whitespace.removeTrailingWhitespace', {
79+
scope: scopeDescriptor
80+
}) && !this.ignore) {
81+
this.removeTrailingWhitespace(editor, editor.getGrammar().scopeName)
82+
}
83+
84+
if (atom.config.get('whitespace.ensureSingleTrailingNewline', {scope: scopeDescriptor})) {
85+
return this.ensureSingleTrailingNewline(editor)
86+
}
87+
})
88+
})
89+
90+
let editorTextInsertedSubscription = editor.onDidInsertText(function (event) {
91+
if (event.text !== '\n') {
92+
return
93+
}
94+
95+
if (!buffer.isRowBlank(event.range.start.row)) {
96+
return
97+
}
98+
99+
let scopeDescriptor = editor.getRootScopeDescriptor()
100+
101+
if (atom.config.get('whitespace.removeTrailingWhitespace', {
102+
scope: scopeDescriptor
103+
})) {
104+
if (!atom.config.get('whitespace.ignoreWhitespaceOnlyLines', {
105+
scope: scopeDescriptor
106+
})) {
107+
return editor.setIndentationForBufferRow(event.range.start.row, 0)
108+
}
109+
}
110+
})
111+
112+
let editorDestroyedSubscription = editor.onDidDestroy(() => {
113+
bufferSavedSubscription.dispose()
114+
editorTextInsertedSubscription.dispose()
115+
editorDestroyedSubscription.dispose()
116+
this.subscriptions.remove(bufferSavedSubscription)
117+
this.subscriptions.remove(editorTextInsertedSubscription)
118+
this.subscriptions.remove(editorDestroyedSubscription)
119+
})
120+
121+
this.subscriptions.add(bufferSavedSubscription)
122+
this.subscriptions.add(editorTextInsertedSubscription)
123+
this.subscriptions.add(editorDestroyedSubscription)
124+
}
125+
126+
removeTrailingWhitespace (editor, grammarScopeName) {
127+
let buffer = editor.getBuffer()
128+
let scopeDescriptor = editor.getRootScopeDescriptor()
129+
130+
let ignoreCurrentLine = atom.config.get('whitespace.ignoreWhitespaceOnCurrentLine', {
131+
scope: scopeDescriptor
132+
})
133+
134+
let ignoreWhitespaceOnlyLines = atom.config.get('whitespace.ignoreWhitespaceOnlyLines', {
135+
scope: scopeDescriptor
136+
})
137+
138+
return buffer.backwardsScan(/[ \t]+$/g, function ({lineText, match, replace}) {
139+
let whitespaceRow = buffer.positionForCharacterIndex(match.index).row
140+
141+
let cursorRows = editor.getCursors().map(cursor => {
142+
return cursor.getBufferRow()
143+
})
144+
145+
if (ignoreCurrentLine && cursorRows.includes(whitespaceRow)) {
146+
return
147+
}
148+
149+
let [whitespace] = match
150+
151+
if (ignoreWhitespaceOnlyLines && whitespace === lineText) {
152+
return
153+
}
154+
155+
if (grammarScopeName === 'source.gfm' && atom.config.get('whitespace.keepMarkdownLineBreakWhitespace')) {
156+
if (!(whitespace.length >= 2 && whitespace !== lineText)) {
157+
return replace('')
158+
}
159+
} else {
160+
return replace('')
161+
}
162+
})
163+
}
164+
165+
ensureSingleTrailingNewline (editor) {
166+
let selectedBufferRanges
167+
let row
168+
let buffer = editor.getBuffer()
169+
let lastRow = buffer.getLastRow()
170+
171+
if (buffer.lineForRow(lastRow) === '') {
172+
row = lastRow - 1
173+
174+
return (() => {
175+
while (row && buffer.lineForRow(row) === '') {
176+
buffer.deleteRow(row--)
177+
}
178+
})()
179+
} else {
180+
selectedBufferRanges = editor.getSelectedBufferRanges()
181+
buffer.append('\n')
182+
return editor.setSelectedBufferRanges(selectedBufferRanges)
183+
}
184+
}
185+
186+
convertTabsToSpaces (editor, convertAllTabs) {
187+
let buffer = editor.getBuffer()
188+
let spacesText = new Array(editor.getTabLength() + 1).join(' ')
189+
let regex = (convertAllTabs ? /\t/g : /^\t+/g)
190+
191+
buffer.transact(function () {
192+
return buffer.scan(regex, function ({replace}) {
193+
return replace(spacesText)
194+
})
195+
})
196+
197+
return editor.setSoftTabs(true)
198+
}
199+
200+
convertSpacesToTabs (editor) {
201+
let buffer = editor.getBuffer()
202+
let scope = editor.getRootScopeDescriptor()
203+
let fileTabSize = editor.getTabLength()
204+
205+
let userTabSize = atom.config.get('editor.tabLength', {
206+
scope: scope
207+
})
208+
209+
let regex = new RegExp(' '.repeat(fileTabSize), 'g')
210+
211+
buffer.transact(function () {
212+
return buffer.scan(/^[ \t]+/g, function ({matchText, replace}) {
213+
return replace(matchText.replace(regex, '\t').replace(/[ ]+\t/g, '\t'))
214+
})
215+
})
216+
217+
editor.setSoftTabs(false)
218+
219+
if (fileTabSize !== userTabSize) {
220+
return editor.setTabLength(userTabSize)
221+
}
222+
}
223+
}

0 commit comments

Comments
 (0)