FEATURE: in vim dev you can focus on spec line in autospec

instructions in bin/notify_file_change
This commit is contained in:
Sam Saffron 2017-04-25 09:12:39 -07:00
parent 5493dc8b81
commit f04fbf911a
4 changed files with 152 additions and 73 deletions

37
bin/notify_file_change Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd ../tmp && pwd )"
SOCKET="$DIR"/file_change.sock
if [[ -e "$SOCKET" ]]; then
echo "$1 $2" | socat - UNIX-CONNECT:$SOCKET >/dev/null 2>/dev/null
if [ $? != 0 ]; then
rm $SOCKET
fi
fi
# To enable:
#
# 1. Install socat
# 2. Add VIM_AUTOSPEC=1 to your environment
# 3. Add the following to your .vimrc
#
# function s:notify_file_change()
# let git_root = fugitive#extract_git_dir(expand("%:p"))
# let root = substitute(git_root, '.git', '', 'g')
# let notify = root . "bin/notify_file_change"
# if executable(notify)
# if executable('socat')
# execute "!" . notify . ' ' . expand("%:p") . " " . line(".")
# end
# end
# " redraw!
# endfunction
# autocmd BufWritePost * silent! call s:notify_file_change()
# What this does?
#
# bin/rake autospec will now automatically try running specs where the actual cursor is located first, then fall back to running spec file

View File

@ -3,6 +3,7 @@ require "thread"
require "fileutils" require "fileutils"
require "autospec/reload_css" require "autospec/reload_css"
require "autospec/base_runner" require "autospec/base_runner"
require "socket_server"
module Autospec; end module Autospec; end
@ -173,6 +174,25 @@ class Autospec::Manager
path = File.expand_path(File.dirname(__FILE__) + "../../..") path = File.expand_path(File.dirname(__FILE__) + "../../..")
if ENV['VIM_AUTOSPEC']
STDERR.puts "Using VIM file listener"
socket_path = (Rails.root + "tmp/file_change.sock").to_s
FileUtils.rm_f(socket_path)
server = SocketServer.new(socket_path)
server.start do |line|
file,line = line.split(' ')
file = file.sub(Rails.root.to_s << "/", "")
# process_change can aquire a mutex and block
# the acceptor
Thread.new do
process_change([[file,line]])
end
"OK"
end
return
end
# to speed up boot we use a thread # to speed up boot we use a thread
["spec", "lib", "app", "config", "test", "vendor", "plugins"].each do |watch| ["spec", "lib", "app", "config", "test", "vendor", "plugins"].each do |watch|
@ -204,7 +224,7 @@ class Autospec::Manager
specs = [] specs = []
hit = false hit = false
files.each do |file| files.each do |file, line|
@runners.each do |runner| @runners.each do |runner|
# reloaders # reloaders
runner.reloaders.each do |k| runner.reloaders.each do |k|
@ -220,22 +240,21 @@ class Autospec::Manager
puts "@@@@@@@@@@@@ #{file} matched a watcher for #{runner}" if @debug puts "@@@@@@@@@@@@ #{file} matched a watcher for #{runner}" if @debug
hit = true hit = true
spec = v ? (v.arity == 1 ? v.call(m) : v.call) : file spec = v ? (v.arity == 1 ? v.call(m) : v.call) : file
specs << [file, spec, runner] if File.exists?(spec) || Dir.exists?(spec) with_line = spec
if spec == file && line
with_line = spec + ":" << line.to_s
end
if File.exists?(spec) || Dir.exists?(spec)
if with_line != spec
specs << [file, spec, runner]
end
specs << [file, with_line, runner]
end
end end
end end
end end
# special watcher for styles/templates
# now handled via libass integration
# Autospec::ReloadCss::WATCHERS.each do |k, _|
# matches = []
# matches << file if k.match(file)
# Autospec::ReloadCss.run_on_change(matches) if matches.present?
# end
end end
queue_specs(specs) if hit queue_specs(specs) if hit
rescue => e rescue => e
fail(e, "failed in watcher") fail(e, "failed in watcher")
end end
@ -260,7 +279,7 @@ class Autospec::Manager
puts "@@@@@@@@@@@@ #{@queue}" if @debug puts "@@@@@@@@@@@@ #{@queue}" if @debug
specs.each do |file, spec, runner| specs.each do |file, spec, runner|
# make sure there's no other instance of this spec in the queue # make sure there's no other instance of this spec in the queue
@queue.delete_if { |_, s, r| s.strip == spec.strip && r == runner } @queue.delete_if { |_, s, r| s.strip.start_with?(spec.strip) && r == runner }
# deal with focused specs # deal with focused specs
if @queue.first && @queue.first[0] == "focus" if @queue.first && @queue.first[0] == "focus"
focus = @queue.shift focus = @queue.shift

80
lib/socket_server.rb Normal file
View File

@ -0,0 +1,80 @@
require 'socket'
class SocketServer
def initialize(socket_path)
@socket_path = socket_path
@server = nil
end
def start(&blk)
@server = UNIXServer.new(@socket_path)
@accept_thread = new_accept_thread
if blk
@blk = blk
end
end
def stop
@server.close if @server
@server = nil
@blk = nil
end
protected
def new_accept_thread
server = @server
Thread.new do
done = false
while !done
done = !accept_connection(server)
end
end
end
def accept_connection(server)
socket = nil
begin
socket = server.accept
rescue IOError
# socket was shut down or something catastrophic like that happened
return false
end
start = Time.now
line = ""
while Time.now - start < 10
if IO.select([socket], nil, nil, 10)
begin
line << socket.read_nonblock(1000)
rescue IO::WaitReadable
sleep 0.001
end
end
break if line.include?("\n")
end
if line.include?("\n")
socket.write get_response(line.strip)
end
true
rescue IOError => e
# nothing to do here, case its normal on shutdown
rescue => e
Rails.logger.warn("Failed to handle connection in stats socket #{e}")
ensure
socket&.close rescue nil
end
def get_response(command)
if @blk
@blk.call(command)
else
raise "Must be implemented by child"
end
end
end

View File

@ -1,70 +1,13 @@
require 'socket' require 'socket_server'
class StatsSocket class StatsSocket < SocketServer
def initialize(socket_path) def initialize(socket_path)
@socket_path = socket_path super(socket_path)
@server = nil
end
def start
@server = UNIXServer.new(@socket_path)
@accept_thread = new_accept_thread
end
def stop
@server.close if @server
@server = nil
end end
protected protected
def new_accept_thread
server = @server
Thread.new do
done = false
while !done
done = !accept_connection(server)
end
end
end
def accept_connection(server)
socket = nil
begin
socket = server.accept
rescue IOError
# socket was shut down or something catastrophic like that happened
return false
end
start = Time.now
line = ""
while Time.now - start < 10
if IO.select([socket], nil, nil, 10)
begin
line << socket.read_nonblock(1000)
rescue IO::WaitReadable
sleep 0.001
end
end
break if line.include?("\n")
end
if line.include?("\n")
socket.write get_response(line.strip)
end
true
rescue IOError => e
# nothing to do here, case its normal on shutdown
rescue => e
Rails.logger.warn("Failed to handle connection in stats socket #{e}")
ensure
socket&.close rescue nil
end
def get_response(command) def get_response(command)
result = result =
case command case command