DecodeSourceDecodeLanguages

class Languages

Represents a context for looking up languages based on file extension or name.

Definitions

def self.all

Create a new languages context with all supported languages.

Signature

returns Languages

A languages context with Ruby support enabled.

Implementation

def self.all
	self.new.tap do |languages|
		languages.add(Language::Ruby.new)
	end
end

def initialize

Initialize a new languages context.

Implementation

def initialize
	@named = {}
	@extensions = {}
end

attr :named

Signature

attribute Hash[String, Language::Generic]

The named languages.

attr :extensions

Signature

attribute Hash[String, Language::Generic]

The languages by extension.

def freeze

Freeze the languages context to prevent further modifications.

Implementation

def freeze
	return unless frozen?
	
	@named.freeze
	@extensions.freeze
	
	super
end

def add(language)

Add a language to this context.

Signature

parameter language Language::Generic

The language to add.

returns self

Implementation

def add(language)
	# Register by name:
	language.names.each do |name|
		@named[name] = language
	end
	
	# Register by file extension:
	language.extensions.each do |extension|
		@extensions[extension] = language
	end
	
	return self
end

def fetch(name)

Fetch a language by name, creating a generic language if needed.

Signature

parameter name String

The name of the language to fetch.

returns Language::Generic?

The language instance for the given name, or nil if frozen and not found.

Implementation

def fetch(name)
	@named.fetch(name) do
		unless @named.frozen?
			@named[name] = Language::Generic.new(name)
		else
			nil
		end
	end
end

def source_for(path)

Create a source object for the given file path.

Signature

parameter path String

The file system path to create a source for.

returns Source?

A source object if the file extension is supported, nil otherwise.

Implementation

def source_for(path)
	extension = File.extname(path)
	
	if language = @extensions[extension]
		Source.new(path, language)
	end
end

REFERENCE = /\A(?<name>[a-z]+)?\s+(?<identifier>.*?)\z/

Signature

constant

Regular expression for parsing language references.

def parse_reference(text, default_language: nil)

Parse a language agnostic reference.

Signature

parameter text String

The text to parse (e.g., "ruby MyModule::MyClass").

parameter default_language Language::Generic?

The default language to use if none specified.

returns Language::Reference?

The parsed reference, or nil if parsing fails.

Implementation

def parse_reference(text, default_language: nil)
	if match = REFERENCE.match(text)
		name = match[:name]
		identifier = match[:identifier]
		
		if name
			language = self.fetch(name) || default_language
		else
			language = default_language
		end
		
		if language && identifier
			return language.reference_for(identifier)
		end
	elsif default_language
		return default_language.reference_for(text)
	end
end

def reference_for(name, identifier)

Create a reference for the given language and identifier.

Signature

parameter name String

The name of the language.

parameter identifier String

The identifier to create a reference for.

returns Language::Reference?

The created reference, or nil if language not found.

Implementation

def reference_for(name, identifier)
	self.fetch(name)&.reference_for(identifier)
end