mirror of
https://github.com/amix/vimrc
synced 2025-07-07 00:15:00 +08:00
Add support for Elixir.
This commit is contained in:
322
sources_non_forked/vim-elixir/spec/spec_helper.rb
Normal file
322
sources_non_forked/vim-elixir/spec/spec_helper.rb
Normal file
@ -0,0 +1,322 @@
|
||||
require 'rspec/expectations'
|
||||
require 'tmpdir'
|
||||
require 'vimrunner'
|
||||
require 'vimrunner/rspec'
|
||||
|
||||
GVIM_PATH_FILE = File.expand_path('../../.gvim_path', __FILE__)
|
||||
|
||||
class Buffer
|
||||
FOLD_PLACEHOLDER = '<!-- FOLD -->'.freeze
|
||||
|
||||
def initialize(vim, type)
|
||||
@file = ".fixture.#{type}"
|
||||
@vim = vim
|
||||
end
|
||||
|
||||
def reindent(content)
|
||||
with_file content do
|
||||
min_indent = content.each_line.map { |line| line[/\s*/].size }.min
|
||||
cmd = "ggVG:s/\\s\\{0,#{min_indent}}//" # remove all indentation
|
||||
cmd += 'gg=G' # force vim to indent the file
|
||||
@vim.normal cmd
|
||||
end
|
||||
end
|
||||
|
||||
def type(content)
|
||||
with_file do
|
||||
@vim.normal 'gg'
|
||||
|
||||
lines = content.each_line
|
||||
count = lines.count
|
||||
@vim.type("i")
|
||||
lines.each_with_index do |line, index|
|
||||
@vim.type("#{line.strip}")
|
||||
@vim.type("<CR>") if index < count - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def syntax(content, pattern)
|
||||
with_file content
|
||||
|
||||
# Using this function with a `pattern` that is not in `content` is pointless.
|
||||
#
|
||||
# @vim.search() silently fails if a pattern is not found and the cursor
|
||||
# won't move. So, if the current cursor position happens to sport the
|
||||
# expected syntax group already, this can lead to false positive tests.
|
||||
#
|
||||
# We work around this by using Vim's search() function, which returns 0 if
|
||||
# there is no match.
|
||||
if @vim.echo("search(#{pattern.inspect})") == '0'
|
||||
return []
|
||||
end
|
||||
|
||||
syngroups = @vim.echo <<~EOF
|
||||
map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
|
||||
EOF
|
||||
|
||||
# From: "['elixirRecordDeclaration', 'elixirAtom']"
|
||||
# To: ["elixirRecordDeclaration", "elixirAtom"]
|
||||
syngroups.gsub!(/["'\[\]]/, '').split(', ')
|
||||
end
|
||||
|
||||
def fold_and_replace(content, fold_on_line)
|
||||
with_file content do
|
||||
cmd = ":set foldmethod=syntax<CR>"
|
||||
cmd += "zO"
|
||||
cmd += "#{fold_on_line}G"
|
||||
cmd += "zc"
|
||||
cmd += "cc#{FOLD_PLACEHOLDER}<Esc>"
|
||||
cmd += ":.s/\s*//<CR>"
|
||||
@vim.normal(cmd)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_file(content = nil)
|
||||
edit_file(content)
|
||||
|
||||
yield if block_given?
|
||||
|
||||
@vim.normal ":w<CR>"
|
||||
@vim.normal ":redraw<CR>"
|
||||
IO.read(@file)
|
||||
end
|
||||
|
||||
def edit_file(content)
|
||||
File.write(@file, content) if content
|
||||
@vim.edit @file
|
||||
end
|
||||
end
|
||||
|
||||
class Differ
|
||||
def self.diff(result, expected)
|
||||
instance.diff(result, expected)
|
||||
end
|
||||
|
||||
def self.instance
|
||||
@instance ||= new
|
||||
end
|
||||
|
||||
def initialize
|
||||
@differ = RSpec::Support::Differ.new(
|
||||
object_preparer: -> (object) do
|
||||
RSpec::Matchers::Composable.surface_descriptions_in(object)
|
||||
end,
|
||||
color: RSpec::Matchers.configuration.color?
|
||||
)
|
||||
end
|
||||
|
||||
def diff(result, expected)
|
||||
@differ.diff_as_string(result, expected)
|
||||
end
|
||||
end
|
||||
|
||||
module ExBuffer
|
||||
def self.new
|
||||
Buffer.new(VIM, :ex)
|
||||
end
|
||||
end
|
||||
|
||||
module EexBuffer
|
||||
def self.new
|
||||
Buffer.new(VIM, :eex)
|
||||
end
|
||||
end
|
||||
|
||||
module HeexBuffer
|
||||
def self.new
|
||||
Buffer.new(VIM, :heex)
|
||||
end
|
||||
end
|
||||
|
||||
module LeexBuffer
|
||||
def self.new
|
||||
Buffer.new(VIM, :leex)
|
||||
end
|
||||
end
|
||||
|
||||
module SurfaceBuffer
|
||||
def self.new
|
||||
Buffer.new(VIM, :sface)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :be_typed_with_right_indent do |syntax|
|
||||
buffer = Buffer.new(VIM, syntax || :ex)
|
||||
|
||||
match do |code|
|
||||
@typed = buffer.type(code)
|
||||
@typed == code
|
||||
end
|
||||
|
||||
failure_message do |code|
|
||||
<<~EOM
|
||||
Expected
|
||||
|
||||
#{@typed}
|
||||
to be indented as
|
||||
|
||||
#{code}
|
||||
|
||||
when typed
|
||||
EOM
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
be_elixir_indentation: :ex,
|
||||
be_eelixir_indentation: :eex,
|
||||
be_heelixir_indentation: :heex,
|
||||
be_leelixir_indentation: :leex,
|
||||
be_surface_indentation: :sface
|
||||
}.each do |matcher, type|
|
||||
RSpec::Matchers.define matcher do
|
||||
buffer = Buffer.new(VIM, type)
|
||||
|
||||
match do |code|
|
||||
reindented = buffer.reindent(code)
|
||||
reindented == code
|
||||
end
|
||||
|
||||
failure_message do |code|
|
||||
<<~EOM
|
||||
Expected
|
||||
|
||||
#{buffer.reindent(code)}
|
||||
to be indented as
|
||||
|
||||
#{code}
|
||||
|
||||
when bulk indented
|
||||
EOM
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
include_elixir_syntax: :ex,
|
||||
include_eelixir_syntax: :eex,
|
||||
include_heelixir_syntax: :heex,
|
||||
include_leelixir_syntax: :leex,
|
||||
include_surface_syntax: :sface
|
||||
}.each do |matcher, type|
|
||||
RSpec::Matchers.define matcher do |syntax, pattern|
|
||||
buffer = Buffer.new(VIM, type)
|
||||
|
||||
match do |code|
|
||||
buffer.syntax(code, pattern).include? syntax.to_s
|
||||
end
|
||||
|
||||
failure_message do |code|
|
||||
<<~EOF
|
||||
expected #{buffer.syntax(code, pattern)}
|
||||
to include syntax '#{syntax}'
|
||||
for pattern: /#{pattern}/
|
||||
in:
|
||||
#{code}
|
||||
EOF
|
||||
end
|
||||
|
||||
failure_message_when_negated do |code|
|
||||
<<~EOF
|
||||
expected #{buffer.syntax(code, pattern)}
|
||||
*NOT* to include syntax '#{syntax}'
|
||||
for pattern: /#{pattern}/
|
||||
in:
|
||||
#{code}
|
||||
EOF
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec::Matchers.define :fold_lines do
|
||||
buffer = Buffer.new(VIM, :ex)
|
||||
|
||||
match do |code|
|
||||
@code = code
|
||||
|
||||
pattern = /# fold\s*$/
|
||||
|
||||
placeholder_set = false
|
||||
@expected = code.each_line.reduce([]) do |acc, line|
|
||||
if line =~ pattern
|
||||
if !placeholder_set
|
||||
placeholder_set = true
|
||||
acc << (Buffer::FOLD_PLACEHOLDER + "\n")
|
||||
end
|
||||
else
|
||||
acc << line
|
||||
end
|
||||
|
||||
acc
|
||||
end.join
|
||||
|
||||
fold_on_line = code.each_line.find_index { |l| l =~ pattern } + 1
|
||||
@actual = buffer.fold_and_replace(code, fold_on_line)
|
||||
|
||||
@expected == @actual
|
||||
end
|
||||
|
||||
failure_message do |code|
|
||||
<<~EOF
|
||||
Folded
|
||||
|
||||
#{@code}
|
||||
and unexpectedly got
|
||||
|
||||
#{@actual}
|
||||
EOF
|
||||
end
|
||||
end
|
||||
|
||||
Vimrunner::RSpec.configure do |config|
|
||||
config.reuse_server = true
|
||||
|
||||
config.start_vim do
|
||||
VIM =
|
||||
if File.exists?(GVIM_PATH_FILE)
|
||||
Vimrunner::Server.new(executable: File.read(GVIM_PATH_FILE).rstrip).start
|
||||
else
|
||||
Vimrunner.start_gvim
|
||||
end
|
||||
VIM.add_plugin(File.expand_path('..', __dir__))
|
||||
cmd = ':filetype off<CR>'
|
||||
cmd += ':filetype plugin indent on<CR>'
|
||||
cmd += ':autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o<CR>' # disable automatic comment continuation
|
||||
cmd += ":set ignorecase<CR>" # make sure we test ignorecase
|
||||
VIM.normal(cmd)
|
||||
VIM
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.order = :random
|
||||
|
||||
# Run a single spec by adding the `focus: true` option
|
||||
config.filter_run_including focus: true
|
||||
config.run_all_when_everything_filtered = true
|
||||
end
|
||||
|
||||
RSpec::Core::ExampleGroup.instance_eval do
|
||||
def i(str)
|
||||
gen_tests(:it, str)
|
||||
end
|
||||
|
||||
def ip(str)
|
||||
gen_tests(:pending, str)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gen_tests(method, str)
|
||||
send method, "\n#{str}" do
|
||||
expect(str).to be_elixir_indentation
|
||||
end
|
||||
|
||||
send method, "typed: \n#{str}" do
|
||||
expect(str).to be_typed_with_right_indent
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user