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

Make the package work with tree-sitter #89

Merged
merged 1 commit into from
Aug 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Make the package work with tree-sitter
  • Loading branch information
maxbrunsfeld committed Aug 31, 2018
commit 6750fe898d5a264ccd931a72cb5a03af0de9983b
132 changes: 132 additions & 0 deletions lib/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
const COMPLETIONS = require('../completions.json')

function getTagNameCompletions (prefix) {
const completions = []
for (const tag in COMPLETIONS.tags) {
const options = COMPLETIONS.tags[tag]
if (firstCharsEqual(tag, prefix)) {
const {description} = options
completions.push({
text: tag,
type: 'tag',
description: description || `HTML <${tag}> tag`,
descriptionMoreURL: description ? getTagDocsURL(tag) : null
})
}
}
return completions
}

function getAttributeNameCompletions (tag, prefix) {
const completions = []
const tagAttributes = getTagAttributes(tag)

for (const attribute of tagAttributes) {
if (firstCharsEqual(attribute, prefix)) {
const options = COMPLETIONS.attributes[attribute]
completions.push({
snippet: (options && options.type === 'flag') ? attribute : `${attribute}="$1"$0`,
displayText: attribute,
type: 'attribute',
rightLabel: `<${tag}>`,
description: `${attribute} attribute local to <${tag}> tags`,
descriptionMoreURL: getLocalAttributeDocsURL(attribute, tag)
})
}
}

for (const attribute in COMPLETIONS.attributes) {
const options = COMPLETIONS.attributes[attribute]
if (options.global && firstCharsEqual(attribute, prefix)) {
completions.push({
snippet: options.type === 'flag' ? attribute : `${attribute}="$1"$0`,
displayText: attribute,
type: 'attribute',
description: options.description ? options.description : `Global ${attribute} attribute`,
descriptionMoreURL: options.description ? getGlobalAttributeDocsURL(attribute) : null
})
}
}

return completions
}

function getAttributeValueCompletions (tag, attribute, prefix) {
const completions = []

const values = getAttributeValues(tag, attribute)
for (const value of values) {
if (firstCharsEqual(value, prefix)) {
completions.push(buildAttributeValueCompletion(tag, attribute, value))
}
}

if (
completions.length === 0 &&
COMPLETIONS.attributes[attribute] &&
COMPLETIONS.attributes[attribute].type === 'boolean'
) {
completions.push(buildAttributeValueCompletion(tag, attribute, 'true'))
completions.push(buildAttributeValueCompletion(tag, attribute, 'false'))
}

return completions
}

function buildAttributeValueCompletion (tag, attribute, value) {
if (COMPLETIONS.attributes[attribute].global) {
return {
text: value,
type: 'value',
description: `${value} value for global ${attribute} attribute`,
descriptionMoreURL: getGlobalAttributeDocsURL(attribute)
}
} else {
return {
text: value,
type: 'value',
rightLabel: `<${tag}>`,
description: `${value} value for ${attribute} attribute local to <${tag}>`,
descriptionMoreURL: getLocalAttributeDocsURL(attribute, tag)
}
}
}

function getAttributeValues (tag, attribute) {
// Some local attributes are valid for multiple tags but have different attribute values
// To differentiate them, they are identified in the completions file as tag/attribute
let result = COMPLETIONS.attributes[`${tag}/${attribute}`]
if (result && result.attribOption) return result.attribOption
result = COMPLETIONS.attributes[attribute]
if (result && result.attribOption) return result.attribOption
return []
}

function getTagAttributes (tag) {
let result = COMPLETIONS.tags[tag]
if (result && result.attributes) return result.attributes
return []
}

function getLocalAttributeDocsURL (attribute, tag) {
return `${getTagDocsURL(tag)}#attr-${attribute}`
}

function getGlobalAttributeDocsURL (attribute) {
return `https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/${attribute}`
}

function getTagDocsURL (tag) {
return `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${tag}`
}

function firstCharsEqual (a, b) {
if (b.length === 0) return true
return a[0].toLowerCase() === b[0].toLowerCase()
}

module.exports = {
getTagNameCompletions,
getAttributeNameCompletions,
getAttributeValueCompletions
}
32 changes: 31 additions & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
const provider = require('./provider')
const getSuggestionsWithTreeSitter = require('./tree-sitter-provider')
const getSuggestionsWithTextMate = require('./text-mate-provider')

const provider = {
selector: '.text.html',
disableForSelector: '.text.html .comment',
priority: 1,
filterSuggestions: true,

getSuggestions (request) {
if (request.editor.getBuffer().getLanguageMode().tree) {
return getSuggestionsWithTreeSitter(request)
} else {
return getSuggestionsWithTextMate(request)
}
},

onDidInsertSuggestion ({editor, suggestion}) {
if (suggestion.type === 'attribute') {
setTimeout(this.triggerAutocomplete.bind(this, editor), 1)
}
},

triggerAutocomplete (editor) {
atom.commands.dispatch(
editor.getElement(),
'autocomplete-plus:activate',
{activatedManually: false}
)
}
}

module.exports = {
activate () {},
Expand Down
Loading