Skip to content

Instantly share code, notes, and snippets.

@endash
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endash/c983565c5c92a7bf0a49 to your computer and use it in GitHub Desktop.
Save endash/c983565c5c92a7bf0a49 to your computer and use it in GitHub Desktop.
Quick and dirty multiple file editing in one window for TextMate - Add the command to a bundle (I use source) with: keycombo ⌘S, save document, discard output. Upon saving a file with the 'scratch' extension the script will parse out all the included files and write them to disk IFF they are in the scratch file's directory or a subdirectory thereof
#!/usr/bin/env ruby
require '[..]/scratch_file.rb'
if (file_name = ENV['TM_FILEPATH']) && File.extname(file_name) == ".scratch"
ScratchFile.new(file_name).write!
end
#file "models/post.rb"
class Post < ActiveRecord::Base
end
#file "controllers/post.rb"
class PostsController < ApplicationController
end
#directory "tests"
#file "models/post.rb"
class TestPost < Minitest::Test
end
#!/usr/bin/env ruby
require 'fileutils'
class ScratchFile
DIRECTORY_REGEX = /^#directory "((.+\/)*[^\/]+)\/?"\s*$/
FILE_REGEX = /^#file "(.+)"\s*$/
def initialize scratch_file_name
@scratch_file_name = scratch_file_name
@working_directory = File.dirname(File.absolute_path(scratch_file_name))
@directory_prefix = ""
end
def write!
files.each do |name, lines|
if should_write_file name
FileUtils.mkdir_p(File.dirname(name))
lines = lines[1..-1] if lines[0] == "\n"
lines = lines[0..-2] if lines[-1] == "\n"
File.write(name, lines.join)
else
puts "!! Warning: File #{name} is outside the working directory (#{@working_directory}) of the scratch file. File NOT written."
end
end
end
def files
{}.tap do |files|
current_file = nil
each_line do |line|
if new_directory_prefix = new_directory_prefix_for_line(line)
@directory_prefix = new_directory_prefix + '/'
current_file = nil
elsif file_name = new_file_name_for_line(line)
files[file_name] = (current_file = [])
elsif current_file
current_file << line
end
end
end
end
def each_line &block
File.foreach(@scratch_file_name) do |line|
block.call(line)
end
end
def new_file_name_for_line (line)
if new_file_name = line[FILE_REGEX, 1]
return File.expand_path("../#{@directory_prefix + new_file_name}", @scratch_file_name)
end
end
def new_directory_prefix_for_line (line)
line[DIRECTORY_REGEX, 1]
end
def should_write_file (file_name)
File.dirname(file_name).start_with?(@working_directory)
end
end
@endash
Copy link
Author

endash commented Feb 22, 2015

Obviously this only works one way. My use case is to quickly build out new classes and the appropriate tests, each in their own files, and edit them together, only having to switch windows to run the tests. I'm not sure if/how I should extend this to keep the scratch file up to date with changes to the individual files, but as it's not intended for "ongoing" use that's not a big concern.

@endash
Copy link
Author

endash commented Feb 22, 2015

Added ability to specify a common directory, to avoid typos. I avoided refactoring the class this time but if it gets any more complex I just might.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment