Skip to content
This repository has been archived by the owner on Aug 7, 2023. It is now read-only.

Commit

Permalink
Merge pull request #18 from AtomLinter/arcanemagus/editor-splits
Browse files Browse the repository at this point in the history
Handle multiple TextEditor for the same content
  • Loading branch information
Arcanemagus authored Jul 13, 2017
2 parents 33e898b + d90480b commit 9d22f5c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 47 deletions.
55 changes: 16 additions & 39 deletions lib/minimap-linter-binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
// eslint-disable-next-line import/no-extraneous-dependencies, import/extensions
import { CompositeDisposable } from 'atom';

const messagePath = message =>
(message.version === 1 ? message.filePath : message.location.file);
const messageRange = message =>
(message.version === 1 ? message.range : message.location.position);
const goodMessage = (message, filePath) =>
(messagePath(message) === filePath && messageRange(message));

export default class MinimapLinterBinding {
constructor(minimap) {
Expand All @@ -17,9 +13,9 @@ export default class MinimapLinterBinding {
this.editor = this.minimap.getTextEditor();
this.markerLayer = this.editor.addMarkerLayer();

this.messages = new Set();
this.markers = new Map();
this.decorations = new Set();
this.idleCallbacks = new Set();

this.subscriptions.add(atom.config.observe('minimap-linter.markerType', (value) => {
this.markerType = value;
Expand All @@ -28,40 +24,23 @@ export default class MinimapLinterBinding {
}));
}

renderDecorations(messagePatch) {
// Parse out what messages have been added/removed
const added = new Set();
const removed = new Set();
const filePath = this.editor.getPath();
messagePatch.added.forEach((message) => {
if (goodMessage(message, filePath)) {
added.add(message);
}
});
messagePatch.removed.forEach((message) => {
if (this.messages.has(message)) {
removed.add(message);
}
});
hasMessage(message) {
return this.markers.has(message);
}

// Handle any removed messages
removed.forEach((message) => {
const marker = this.markers.get(message);
if (marker) {
marker.destroy();
}
this.messages.delete(message);
this.markers.delete(message);
});
addMessage(message) {
const markerRange = messageRange(message);
const marker = this.markerLayer.markBufferRange(markerRange, { invalidate: 'never' });
this.markers.set(message, marker);
this.decorateMarker(marker, message);
}

// Handle any added messages
added.forEach((message) => {
const markerRange = messageRange(message);
const marker = this.markerLayer.markBufferRange(markerRange, { invalidate: 'never' });
this.markers.set(message, marker);
this.messages.add(message);
this.decorateMarker(marker, message);
});
removeMessage(message) {
const marker = this.markers.get(message);
if (marker) {
marker.destroy();
}
this.markers.delete(message);
}

decorateMarker(marker, message) {
Expand All @@ -82,13 +61,11 @@ export default class MinimapLinterBinding {
this.removeDecorations();
this.markers.forEach(marker => marker.destroy());
this.markers.clear();
this.messages.clear();
}

destroy() {
this.removeMessages();
this.markerLayer.destroy();
this.subscriptions.dispose();
}

}
59 changes: 51 additions & 8 deletions lib/minimap-linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@
import { CompositeDisposable } from 'atom';
import MinimapLinterBinding from './minimap-linter-binding';

const bindings = new Map();
const messagePath = message =>
(message.version === 1 ? message.filePath : message.location.file);
const messageRange = message =>
(message.version === 1 ? message.range : message.location.position);
const goodMessage = (message, filePath) =>
(messagePath(message) === filePath && messageRange(message));

export default {
// Atom package lifecycle events start
activate() {
this.bindings = new Map();
this.idleCallbacks = new Set();
let depsCallbackID;
const installMinimapLinterDeps = () => {
Expand All @@ -19,7 +25,9 @@ export default {
};
depsCallbackID = window.requestIdleCallback(installMinimapLinterDeps);
this.idleCallbacks.add(depsCallbackID);

this.subscriptions = new CompositeDisposable();
this.messageCache = new Set();
},

deactivate() {
Expand All @@ -30,6 +38,7 @@ export default {
}
this.minimapProvider.unregisterPlugin('linter');
this.minimapProvider = null;
this.messageCache.clear();
},
// Atom package lifecycle events end

Expand All @@ -42,15 +51,36 @@ export default {

// LinterUI (for messages)
provideUI() {
const minimapBindings = this.bindings;
const messageCache = this.messageCache;
return {
name: 'minimap-linter',
render(messagePatch) {
bindings.forEach(binding => binding.renderDecorations(messagePatch));
// Parse out what messages have been added/removed
const added = new Set();
const removed = new Set();
minimapBindings.forEach((binding, minimap) => {
const filePath = minimap.getTextEditor().getPath();
messagePatch.added.forEach((message) => {
if (goodMessage(message, filePath)) {
added.add(message);
binding.addMessage(message);
}
});
messagePatch.removed.forEach((message) => {
removed.add(message);
if (binding.hasMessage(message)) {
binding.removeMessage(message);
}
});
});
added.forEach(message => messageCache.add(message));
removed.forEach(message => messageCache.delete(message));
},
didBeginLinting() {},
didFinishLinting() {},
dispose() {
bindings.forEach(binding => binding.removeMessages());
minimapBindings.forEach(binding => binding.removeMessages());
},
};
},
Expand All @@ -73,25 +103,38 @@ export default {
// Handle each minimap
this.minimapsSubscription = this.minimapProvider.observeMinimaps((minimap) => {
const binding = new MinimapLinterBinding(minimap);
bindings.set(minimap, binding);
this.bindings.set(minimap, binding);
const subscription = minimap.onDidDestroy(() => {
binding.destroy();
this.subscriptions.remove(subscription);
subscription.dispose();
bindings.delete(minimap);
this.bindings.delete(minimap);
});

this.subscriptions.add(subscription);

// Force rendering of old messages after a small delay
let oldMsgCallbackID;
const renderOldMessages = () => {
this.idleCallbacks.delete(oldMsgCallbackID);
const filePath = minimap.getTextEditor().getPath();
this.messageCache.forEach((message) => {
if (goodMessage(message, filePath)) {
binding.addMessage(message);
}
});
};
oldMsgCallbackID = window.requestIdleCallback(renderOldMessages);
this.idleCallbacks.add(oldMsgCallbackID);
});
},

deactivatePlugin() {
if (!this.active) {
return;
}
bindings.forEach((binding, minimap) => {
this.bindings.forEach((binding, minimap) => {
binding.destroy();
bindings.delete(minimap);
this.bindings.delete(minimap);
});
this.minimapsSubscription.dispose();
this.subscriptions.dispose();
Expand Down

0 comments on commit 9d22f5c

Please sign in to comment.