123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- let SpellCheckView;
- const _ = require('underscore-plus');
- const { CompositeDisposable } = require('atom');
- const SpellCheckTask = require('./spell-check-task');
- let CorrectionsView = null;
- module.exports = SpellCheckView = class SpellCheckView {
- constructor(editor, spellCheckModule, manager) {
- this.addContextMenuEntries = this.addContextMenuEntries.bind(this);
- this.makeCorrection = this.makeCorrection.bind(this);
- this.editor = editor;
- this.spellCheckModule = spellCheckModule;
- this.manager = manager;
- this.disposables = new CompositeDisposable();
- this.initializeMarkerLayer();
- this.taskWrapper = new SpellCheckTask(this.manager);
- this.correctMisspellingCommand = atom.commands.add(
- atom.views.getView(this.editor),
- 'spell-check:correct-misspelling',
- () => {
- let marker;
- if (
- (marker = this.markerLayer.findMarkers({
- containsBufferPosition: this.editor.getCursorBufferPosition(),
- })[0])
- ) {
- if (CorrectionsView == null) {
- CorrectionsView = require('./corrections-view');
- }
- if (this.correctionsView != null) {
- this.correctionsView.destroy();
- }
- this.correctionsView = new CorrectionsView(
- this.editor,
- this.getCorrections(marker),
- marker,
- this,
- this.updateMisspellings
- );
- return this.correctionsView.attach();
- }
- }
- );
- atom.views
- .getView(this.editor)
- .addEventListener('contextmenu', this.addContextMenuEntries);
- this.disposables.add(
- this.editor.onDidChangePath(() => {
- return this.subscribeToBuffer();
- })
- );
- this.disposables.add(
- this.editor.onDidChangeGrammar(() => {
- return this.subscribeToBuffer();
- })
- );
- this.disposables.add(
- atom.config.onDidChange('editor.fontSize', () => {
- return this.subscribeToBuffer();
- })
- );
- this.disposables.add(
- atom.config.onDidChange('spell-check.grammars', () => {
- return this.subscribeToBuffer();
- })
- );
- this.subscribeToBuffer();
- this.disposables.add(this.editor.onDidDestroy(this.destroy.bind(this)));
- }
- initializeMarkerLayer() {
- this.markerLayer = this.editor.addMarkerLayer({
- maintainHistory: false,
- });
- return (this.markerLayerDecoration = this.editor.decorateMarkerLayer(
- this.markerLayer,
- {
- type: 'highlight',
- class: 'spell-check-misspelling',
- deprecatedRegionClass: 'misspelling',
- }
- ));
- }
- destroy() {
- this.unsubscribeFromBuffer();
- this.disposables.dispose();
- this.taskWrapper.terminate();
- this.markerLayer.destroy();
- this.markerLayerDecoration.destroy();
- this.correctMisspellingCommand.dispose();
- if (this.correctionsView != null) {
- this.correctionsView.destroy();
- }
- return this.clearContextMenuEntries();
- }
- unsubscribeFromBuffer() {
- this.destroyMarkers();
- if (this.buffer != null) {
- this.bufferDisposable.dispose();
- return (this.buffer = null);
- }
- }
- subscribeToBuffer() {
- this.unsubscribeFromBuffer();
- if (this.spellCheckCurrentGrammar()) {
- this.buffer = this.editor.getBuffer();
- this.bufferDisposable = new CompositeDisposable(
- this.buffer.onDidStopChanging(
- () => this.updateMisspellings(),
- this.editor.onDidTokenize(() => this.updateMisspellings())
- )
- );
- return this.updateMisspellings();
- }
- }
- spellCheckCurrentGrammar() {
- const grammar = this.editor.getGrammar().scopeName;
- return _.contains(atom.config.get('spell-check.grammars'), grammar);
- }
- destroyMarkers() {
- this.markerLayer.destroy();
- this.markerLayerDecoration.destroy();
- return this.initializeMarkerLayer();
- }
- addMarkers(misspellings) {
- return (() => {
- const result = [];
- for (let misspelling of misspellings) {
- const scope = this.editor.scopeDescriptorForBufferPosition(
- misspelling[0]
- );
- if (!this.scopeIsExcluded(scope)) {
- result.push(
- this.markerLayer.markBufferRange(misspelling, {
- invalidate: 'touch',
- })
- );
- } else {
- result.push(undefined);
- }
- }
- return result;
- })();
- }
- updateMisspellings() {
- return this.taskWrapper.start(this.editor, (misspellings) => {
- this.destroyMarkers();
- if (this.buffer != null) {
- return this.addMarkers(misspellings);
- }
- });
- }
- getCorrections(marker) {
- // Build up the arguments object for this buffer and text.
- let projectPath = null;
- let relativePath = null;
- if (this.buffer != null && this.buffer.file && this.buffer.file.path) {
- [projectPath, relativePath] = atom.project.relativizePath(
- this.buffer.file.path
- );
- }
- const args = {
- projectPath,
- relativePath,
- };
- // Get the misspelled word and then request corrections.
- const misspelling = this.editor.getTextInBufferRange(
- marker.getBufferRange()
- );
- return this.manager.suggest(args, misspelling);
- }
- addContextMenuEntries(mouseEvent) {
- let marker;
- this.clearContextMenuEntries();
- // Get buffer position of the right click event. If the click happens outside
- // the boundaries of any text, the method defaults to the buffer position of
- // the last character in the editor.
- const currentScreenPosition = atom.views
- .getView(this.editor)
- .component.screenPositionForMouseEvent(mouseEvent);
- const currentBufferPosition = this.editor.bufferPositionForScreenPosition(
- currentScreenPosition
- );
- // Check to see if the selected word is incorrect.
- if (
- (marker = this.markerLayer.findMarkers({
- containsBufferPosition: currentBufferPosition,
- })[0])
- ) {
- const corrections = this.getCorrections(marker);
- if (corrections.length > 0) {
- this.spellCheckModule.contextMenuEntries.push({
- menuItem: atom.contextMenu.add({
- 'atom-text-editor': [{ type: 'separator' }],
- }),
- });
- let correctionIndex = 0;
- for (let correction of corrections) {
- const contextMenuEntry = {};
- // Register new command for correction.
- var commandName =
- 'spell-check:correct-misspelling-' + correctionIndex;
- contextMenuEntry.command = ((
- correction,
- contextMenuEntry
- ) => {
- return atom.commands.add(
- atom.views.getView(this.editor),
- commandName,
- () => {
- this.makeCorrection(correction, marker);
- return this.clearContextMenuEntries();
- }
- );
- })(correction, contextMenuEntry);
- // Add new menu item for correction.
- contextMenuEntry.menuItem = atom.contextMenu.add({
- 'atom-text-editor': [
- { label: correction.label, command: commandName },
- ],
- });
- this.spellCheckModule.contextMenuEntries.push(
- contextMenuEntry
- );
- correctionIndex++;
- }
- return this.spellCheckModule.contextMenuEntries.push({
- menuItem: atom.contextMenu.add({
- 'atom-text-editor': [{ type: 'separator' }],
- }),
- });
- }
- }
- }
- makeCorrection(correction, marker) {
- if (correction.isSuggestion) {
- // Update the buffer with the correction.
- this.editor.setSelectedBufferRange(marker.getBufferRange());
- return this.editor.insertText(correction.suggestion);
- } else {
- // Build up the arguments object for this buffer and text.
- let projectPath = null;
- let relativePath = null;
- if (
- this.editor.buffer != null &&
- this.editor.buffer.file &&
- this.editor.buffer.file.path
- ) {
- [projectPath, relativePath] = atom.project.relativizePath(
- this.editor.buffer.file.path
- );
- }
- const args = {
- id: this.id,
- projectPath,
- relativePath,
- };
- // Send the "add" request to the plugin.
- correction.plugin.add(args, correction);
- // Update the buffer to handle the corrections.
- return this.updateMisspellings.bind(this)();
- }
- }
- clearContextMenuEntries() {
- for (let entry of this.spellCheckModule.contextMenuEntries) {
- if (entry.command != null) {
- entry.command.dispose();
- }
- if (entry.menuItem != null) {
- entry.menuItem.dispose();
- }
- }
- return (this.spellCheckModule.contextMenuEntries = []);
- }
- scopeIsExcluded(scopeDescriptor, excludedScopes) {
- return this.spellCheckModule.excludedScopeRegexLists.some((regexList) =>
- scopeDescriptor.scopes.some((scopeName) =>
- regexList.every((regex) => regex.test(scopeName))
- )
- );
- }
- };
|