Atom/packages/grammar-selector/lib/grammar-list-view.js

149 lines
4.1 KiB
JavaScript

const SelectListView = require('atom-select-list');
module.exports = class GrammarListView {
constructor() {
this.autoDetect = { name: 'Auto Detect' };
this.selectListView = new SelectListView({
itemsClassList: ['mark-active'],
items: [],
filterKeyForItem: grammar => grammar.name,
elementForItem: grammar => {
const grammarName = grammar.name || grammar.scopeName;
const element = document.createElement('li');
if (grammar === this.currentGrammar) {
element.classList.add('active');
}
element.textContent = grammarName;
element.dataset.grammar = grammarName;
const div = document.createElement('div');
div.classList.add('pull-right');
if (isTreeSitter(grammar)) {
const parser = document.createElement('span');
parser.classList.add(
'grammar-selector-parser',
'badge',
'badge-success'
);
parser.textContent = 'Tree-sitter';
parser.setAttribute(
'title',
'(Recommended) A faster parser with improved syntax highlighting & code navigation support.'
);
div.appendChild(parser);
}
if (grammar.scopeName) {
const scopeName = document.createElement('scopeName');
scopeName.classList.add('badge', 'badge-info');
scopeName.textContent = grammar.scopeName;
div.appendChild(scopeName);
element.appendChild(div);
}
return element;
},
didConfirmSelection: grammar => {
this.cancel();
if (grammar === this.autoDetect) {
atom.textEditors.clearGrammarOverride(this.editor);
} else {
atom.grammars.assignGrammar(this.editor, grammar);
}
},
didCancelSelection: () => {
this.cancel();
}
});
this.selectListView.element.classList.add('grammar-selector');
}
destroy() {
this.cancel();
return this.selectListView.destroy();
}
cancel() {
if (this.panel != null) {
this.panel.destroy();
}
this.panel = null;
this.currentGrammar = null;
if (this.previouslyFocusedElement) {
this.previouslyFocusedElement.focus();
this.previouslyFocusedElement = null;
}
}
attach() {
this.previouslyFocusedElement = document.activeElement;
if (this.panel == null) {
this.panel = atom.workspace.addModalPanel({ item: this.selectListView });
}
this.selectListView.focus();
this.selectListView.reset();
}
async toggle() {
if (this.panel != null) {
this.cancel();
return;
}
const editor = atom.workspace.getActiveTextEditor();
if (editor) {
this.editor = editor;
this.currentGrammar = this.editor.getGrammar();
if (this.currentGrammar === atom.grammars.nullGrammar) {
this.currentGrammar = this.autoDetect;
}
let grammars = atom.grammars
.getGrammars({ includeTreeSitter: true })
.filter(grammar => {
return grammar !== atom.grammars.nullGrammar && grammar.name;
});
if (atom.config.get('grammar-selector.hideDuplicateTextMateGrammars')) {
const blacklist = new Set();
grammars.forEach(grammar => {
if (isTreeSitter(grammar)) {
blacklist.add(grammar.name);
}
});
grammars = grammars.filter(
grammar => isTreeSitter(grammar) || !blacklist.has(grammar.name)
);
}
grammars.sort((a, b) => {
if (a.scopeName === 'text.plain') {
return -1;
} else if (b.scopeName === 'text.plain') {
return 1;
} else if (a.name === b.name) {
return compareGrammarType(a, b);
}
return a.name.localeCompare(b.name);
});
grammars.unshift(this.autoDetect);
await this.selectListView.update({ items: grammars });
this.attach();
}
}
};
function isTreeSitter(grammar) {
return grammar.constructor.name === 'TreeSitterGrammar';
}
function compareGrammarType(a, b) {
if (isTreeSitter(a)) {
return -1;
} else if (isTreeSitter(b)) {
return 1;
}
return 0;
}