Decaffeinate src/grammar-registry.coffee

This commit is contained in:
Jason Rudolph
2017-10-07 08:30:44 -04:00
parent 65efc99ef9
commit a00f619643
2 changed files with 171 additions and 130 deletions

View File

@@ -1,130 +0,0 @@
_ = require 'underscore-plus'
FirstMate = require 'first-mate'
Token = require './token'
fs = require 'fs-plus'
Grim = require 'grim'
PathSplitRegex = new RegExp("[/.]")
# Extended: Syntax class holding the grammars used for tokenizing.
#
# An instance of this class is always available as the `atom.grammars` global.
#
# The Syntax class also contains properties for things such as the
# language-specific comment regexes. See {::getProperty} for more details.
module.exports =
class GrammarRegistry extends FirstMate.GrammarRegistry
constructor: ({@config}={}) ->
super(maxTokensPerLine: 100, maxLineLength: 1000)
createToken: (value, scopes) -> new Token({value, scopes})
# Extended: Select a grammar for the given file path and file contents.
#
# This picks the best match by checking the file path and contents against
# each grammar.
#
# * `filePath` A {String} file path.
# * `fileContents` A {String} of text for the file path.
#
# Returns a {Grammar}, never null.
selectGrammar: (filePath, fileContents) ->
@selectGrammarWithScore(filePath, fileContents).grammar
selectGrammarWithScore: (filePath, fileContents) ->
bestMatch = null
highestScore = -Infinity
for grammar in @grammars
score = @getGrammarScore(grammar, filePath, fileContents)
if score > highestScore or not bestMatch?
bestMatch = grammar
highestScore = score
{grammar: bestMatch, score: highestScore}
# Extended: Returns a {Number} representing how well the grammar matches the
# `filePath` and `contents`.
getGrammarScore: (grammar, filePath, contents) ->
contents = fs.readFileSync(filePath, 'utf8') if not contents? and fs.isFileSync(filePath)
score = @getGrammarPathScore(grammar, filePath)
if score > 0 and not grammar.bundledPackage
score += 0.25
if @grammarMatchesContents(grammar, contents)
score += 0.125
score
getGrammarPathScore: (grammar, filePath) ->
return -1 unless filePath
filePath = filePath.replace(/\\/g, '/') if process.platform is 'win32'
pathComponents = filePath.toLowerCase().split(PathSplitRegex)
pathScore = -1
fileTypes = grammar.fileTypes
if customFileTypes = @config.get('core.customFileTypes')?[grammar.scopeName]
fileTypes = fileTypes.concat(customFileTypes)
for fileType, i in fileTypes
fileTypeComponents = fileType.toLowerCase().split(PathSplitRegex)
pathSuffix = pathComponents[-fileTypeComponents.length..-1]
if _.isEqual(pathSuffix, fileTypeComponents)
pathScore = Math.max(pathScore, fileType.length)
if i >= grammar.fileTypes.length
pathScore += 0.5
pathScore
grammarMatchesContents: (grammar, contents) ->
return false unless contents? and grammar.firstLineRegex?
escaped = false
numberOfNewlinesInRegex = 0
for character in grammar.firstLineRegex.source
switch character
when '\\'
escaped = not escaped
when 'n'
numberOfNewlinesInRegex++ if escaped
escaped = false
else
escaped = false
lines = contents.split('\n')
grammar.firstLineRegex.testSync(lines[0..numberOfNewlinesInRegex].join('\n'))
# Deprecated: Get the grammar override for the given file path.
#
# * `filePath` A {String} file path.
#
# Returns a {String} such as `"source.js"`.
grammarOverrideForPath: (filePath) ->
Grim.deprecate 'Use atom.textEditors.getGrammarOverride(editor) instead'
if editor = getEditorForPath(filePath)
atom.textEditors.getGrammarOverride(editor)
# Deprecated: Set the grammar override for the given file path.
#
# * `filePath` A non-empty {String} file path.
# * `scopeName` A {String} such as `"source.js"`.
#
# Returns undefined
setGrammarOverrideForPath: (filePath, scopeName) ->
Grim.deprecate 'Use atom.textEditors.setGrammarOverride(editor, scopeName) instead'
if editor = getEditorForPath(filePath)
atom.textEditors.setGrammarOverride(editor, scopeName)
return
# Deprecated: Remove the grammar override for the given file path.
#
# * `filePath` A {String} file path.
#
# Returns undefined.
clearGrammarOverrideForPath: (filePath) ->
Grim.deprecate 'Use atom.textEditors.clearGrammarOverride(editor) instead'
if editor = getEditorForPath(filePath)
atom.textEditors.clearGrammarOverride(editor)
return
getEditorForPath = (filePath) ->
if filePath?
atom.workspace.getTextEditors().find (editor) ->
editor.getPath() is filePath

171
src/grammar-registry.js Normal file
View File

@@ -0,0 +1,171 @@
const _ = require('underscore-plus')
const FirstMate = require('first-mate')
const Token = require('./token')
const fs = require('fs-plus')
const Grim = require('grim')
const PathSplitRegex = new RegExp('[/.]')
// Extended: Syntax class holding the grammars used for tokenizing.
//
// An instance of this class is always available as the `atom.grammars` global.
//
// The Syntax class also contains properties for things such as the
// language-specific comment regexes. See {::getProperty} for more details.
module.exports =
class GrammarRegistry extends FirstMate.GrammarRegistry {
constructor ({config} = {}) {
super({maxTokensPerLine: 100, maxLineLength: 1000})
this.config = config
}
createToken (value, scopes) {
return new Token({value, scopes})
}
// Extended: Select a grammar for the given file path and file contents.
//
// This picks the best match by checking the file path and contents against
// each grammar.
//
// * `filePath` A {String} file path.
// * `fileContents` A {String} of text for the file path.
//
// Returns a {Grammar}, never null.
selectGrammar (filePath, fileContents) {
return this.selectGrammarWithScore(filePath, fileContents).grammar
}
selectGrammarWithScore (filePath, fileContents) {
let bestMatch = null
let highestScore = -Infinity
for (let grammar of this.grammars) {
const score = this.getGrammarScore(grammar, filePath, fileContents)
if ((score > highestScore) || (bestMatch == null)) {
bestMatch = grammar
highestScore = score
}
}
return {grammar: bestMatch, score: highestScore}
}
// Extended: Returns a {Number} representing how well the grammar matches the
// `filePath` and `contents`.
getGrammarScore (grammar, filePath, contents) {
if ((contents == null) && fs.isFileSync(filePath)) {
contents = fs.readFileSync(filePath, 'utf8')
}
let score = this.getGrammarPathScore(grammar, filePath)
if ((score > 0) && !grammar.bundledPackage) {
score += 0.25
}
if (this.grammarMatchesContents(grammar, contents)) {
score += 0.125
}
return score
}
getGrammarPathScore (grammar, filePath) {
if (!filePath) { return -1 }
if (process.platform === 'win32') { filePath = filePath.replace(/\\/g, '/') }
const pathComponents = filePath.toLowerCase().split(PathSplitRegex)
let pathScore = -1
let customFileTypes
if (this.config.get('core.customFileTypes')) {
customFileTypes = this.config.get('core.customFileTypes')[grammar.scopeName]
}
let { fileTypes } = grammar
if (customFileTypes) {
fileTypes = fileTypes.concat(customFileTypes)
}
for (let i = 0; i < fileTypes.length; i++) {
const fileType = fileTypes[i]
const fileTypeComponents = fileType.toLowerCase().split(PathSplitRegex)
const pathSuffix = pathComponents.slice(-fileTypeComponents.length)
if (_.isEqual(pathSuffix, fileTypeComponents)) {
pathScore = Math.max(pathScore, fileType.length)
if (i >= grammar.fileTypes.length) {
pathScore += 0.5
}
}
}
return pathScore
}
grammarMatchesContents (grammar, contents) {
if ((contents == null) || (grammar.firstLineRegex == null)) { return false }
let escaped = false
let numberOfNewlinesInRegex = 0
for (let character of grammar.firstLineRegex.source) {
switch (character) {
case '\\':
escaped = !escaped
break
case 'n':
if (escaped) { numberOfNewlinesInRegex++ }
escaped = false
break
default:
escaped = false
}
}
const lines = contents.split('\n')
return grammar.firstLineRegex.testSync(lines.slice(0, numberOfNewlinesInRegex + 1).join('\n'))
}
// Deprecated: Get the grammar override for the given file path.
//
// * `filePath` A {String} file path.
//
// Returns a {String} such as `"source.js"`.
grammarOverrideForPath (filePath) {
Grim.deprecate('Use atom.textEditors.getGrammarOverride(editor) instead')
const editor = getEditorForPath(filePath)
if (editor) {
return atom.textEditors.getGrammarOverride(editor)
}
}
// Deprecated: Set the grammar override for the given file path.
//
// * `filePath` A non-empty {String} file path.
// * `scopeName` A {String} such as `"source.js"`.
//
// Returns undefined.
setGrammarOverrideForPath (filePath, scopeName) {
Grim.deprecate('Use atom.textEditors.setGrammarOverride(editor, scopeName) instead')
const editor = getEditorForPath(filePath)
if (editor) {
atom.textEditors.setGrammarOverride(editor, scopeName)
}
}
// Deprecated: Remove the grammar override for the given file path.
//
// * `filePath` A {String} file path.
//
// Returns undefined.
clearGrammarOverrideForPath (filePath) {
Grim.deprecate('Use atom.textEditors.clearGrammarOverride(editor) instead')
const editor = getEditorForPath(filePath)
if (editor) {
atom.textEditors.clearGrammarOverride(editor)
}
}
}
function getEditorForPath (filePath) {
if (filePath != null) {
return atom.workspace.getTextEditors().find(editor => editor.getPath() === filePath)
}
}