├── feature ├── support │ └── env.rb └── config.feature ├── Rakefile ├── lib ├── rstrip.rb └── rstrip │ ├── version.rb │ ├── templates │ └── rstrip.tt.txt │ ├── cli.rb │ └── rstrip.rb ├── .gitignore ├── bin └── rstrip ├── Gemfile ├── spec └── rstrip_spec.rb ├── rstrip.gemspec └── README.md /feature/support/env.rb: -------------------------------------------------------------------------------- 1 | require 'aruba/cucumber' -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | -------------------------------------------------------------------------------- /lib/rstrip.rb: -------------------------------------------------------------------------------- 1 | module Rstrip 2 | # Your code goes here... 3 | end -------------------------------------------------------------------------------- /lib/rstrip/version.rb: -------------------------------------------------------------------------------- 1 | module Rstrip 2 | VERSION = "0.0.4" 3 | end 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | Gemfile.lock 4 | pkg/* 5 | tmp/* 6 | .rstrip 7 | -------------------------------------------------------------------------------- /bin/rstrip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rstrip/cli' 4 | Rstrip::CLI.start -------------------------------------------------------------------------------- /lib/rstrip/templates/rstrip.tt.txt: -------------------------------------------------------------------------------- 1 | rb 2 | erb 3 | haml 4 | js 5 | coffee 6 | css 7 | scss 8 | rdoc 9 | feature 10 | yml -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | group :development do 4 | gem 'rake' 5 | end 6 | # Specify your gem's dependencies in rstrip.gemspec 7 | gemspec 8 | -------------------------------------------------------------------------------- /spec/rstrip_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rstrip/rstrip' 2 | 3 | describe Rstrip::Rstrip do 4 | 5 | it "should remove right whitespace" do 6 | Rstrip::Rstrip.rstrip("Lorem ipsum \n").should == "Lorem ipsum\n" 7 | end 8 | 9 | it "should remove right tab" do 10 | Rstrip::Rstrip.rstrip("Lorem ipsum\t\n").should == "Lorem ipsum\n" 11 | end 12 | 13 | it "should remove right form" do 14 | Rstrip::Rstrip.rstrip("Lorem ipsum\f\n").should == "Lorem ipsum\n" 15 | end 16 | 17 | it "should remove right carriage return" do 18 | Rstrip::Rstrip.rstrip("Lorem ipsum\r\n").should == "Lorem ipsum\n" 19 | end 20 | 21 | it "should remove multiple whitespace" do 22 | Rstrip::Rstrip.rstrip("Lorem ipsum \f\t \n").should == "Lorem ipsum\n" 23 | end 24 | 25 | it "should not remove right newline\n" do 26 | Rstrip::Rstrip.rstrip("Lorem ipsum\n").should == "Lorem ipsum\n" 27 | Rstrip::Rstrip.rstrip("Lorem ipsum\n\n").should == "Lorem ipsum\n" 28 | Rstrip::Rstrip.rstrip("Lorem ipsum\r\n").should == "Lorem ipsum\n" 29 | end 30 | 31 | end -------------------------------------------------------------------------------- /rstrip.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "rstrip/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "rstrip" 7 | s.version = Rstrip::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["zhengjia"] 10 | s.email = ["jiazheng@live.com"] 11 | s.homepage = "" 12 | s.summary = %q{A ruby executable that removes the trailing white space in the current project directory} 13 | s.description = %q{A ruby executable that removes the trailing white space in the current project directory. It also remove the last empty line if there is one} 14 | 15 | s.rubyforge_project = "rstrip" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | 22 | s.add_development_dependency "rspec", "~> 2.13.0" 23 | s.add_development_dependency "aruba", "~> 0.5.3" 24 | s.add_dependency "thor" 25 | end 26 | -------------------------------------------------------------------------------- /lib/rstrip/cli.rb: -------------------------------------------------------------------------------- 1 | require 'thor' 2 | require 'rstrip/rstrip' 3 | module Rstrip 4 | class CLI < Thor 5 | 6 | include Thor::Actions 7 | 8 | desc "config", "generate: to generate a .rstrip file. list: to show the files that will be operated on" 9 | long_desc <<-D 10 | config can receive two arguments. 11 | 12 | generate: Generate a .rstrip config file containing file extensions rstrip will operate on.Defaults to the current 13 | directory.Use --global true to generate .rstrip to the user's home directory.\n 14 | list: Show the location of the .rstrip config file that will be used. And show a list of files that will be 15 | operated on based on the .rstrip config file 16 | D 17 | method_option :global, :type => :boolean, :aliases => "-g", :default => false 18 | def config(task) 19 | case task.downcase 20 | when 'generate' 21 | if options[:global] 22 | template("rstrip.tt.txt", "#{Dir.home}/.rstrip") 23 | else 24 | template("rstrip.tt.txt", "#{Dir.pwd}/.rstrip") 25 | end 26 | when 'list' 27 | Rstrip.list 28 | end 29 | end 30 | 31 | desc "process", "run rstrip in the current folder recursively" 32 | def process 33 | Rstrip.list.collect{ |f| Rstrip.process(f) } 34 | end 35 | 36 | def self.source_root 37 | File.dirname(__FILE__) + "/templates" 38 | end 39 | 40 | end 41 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ------------ 3 | 4 | rstrip provides a ruby executable that removes the trailing white space in the current project directory. 5 | 6 | It also remove empty lines at the end of a file. 7 | 8 | It's configurable on the file types it will operate on. 9 | 10 | Usage 11 | ----- 12 | 13 | * Install the gem: `gem install rstrip` 14 | * In your project folder run `rstrip config generate`, or run `rstrip config generate --global true` to generate the config file in your home directory 15 | * Modify the list of file extensions in the .rstrip config file 16 | * In your project folder run `rstrip process` 17 | * Examine the changes and commit the code 18 | 19 | Alternatives 20 | ------------ 21 | 22 | There are a lot of ways to do the similar thing: 23 | 24 | * textmate bundle https://github.com/mocoso/code-beautifier.tmbundle 25 | 26 | * textmate marco http://mjijackson.com/2009/01/textmate-macro-remove-trailing-space-and-save 27 | 28 | * bash http://stackoverflow.com/questions/149057/how-to-removing-trailing-whitespace-of-all-files-recursively 29 | 30 | * Use a git prehook http://stackoverflow.com/questions/591923/make-git-automatically-remove-trailing-whitespace-before-committing 31 | 32 | I used the textmate marco before. The problem with textmate bundle or marco is they only modify the file if you edit and save it, which makes the commits harder to read as you will remove white spaces gradually. rstrip gets it done all in once in the folder level. Then you can use the bundle or marco with a fresh start. 33 | 34 | rstrip also tries to make it as easy as possible so you don't need to remember the cryptic bash or perl commands. -------------------------------------------------------------------------------- /feature/config.feature: -------------------------------------------------------------------------------- 1 | Feature: Config 2 | In order to use rstrip 3 | I have to have a .rstrip in the current directory or my home directory 4 | 5 | Scenario: Generate the .rstrip in the current directory 6 | When I run `rstrip config generate` 7 | Then a file named ".rstrip" should exist 8 | And the file ".rstrip" should contain "rb" 9 | And the file ".rstrip" should contain "erb" 10 | 11 | Scenario: Prompt to run the generator 12 | When I run `rstrip config list` 13 | Then the output should contain "Please run 'rstrip config generate'" 14 | 15 | Scenario: Show the list of files that will be operated on 16 | Given a file named ".rstrip" with: 17 | """ 18 | rb 19 | erb 20 | """ 21 | Given an empty file named "lib/dummy.rb" 22 | Given an empty file named "dummy.erb" 23 | When I run `rstrip config list` 24 | Then the output should contain "in the current directory" 25 | And the stdout should contain "lib/dummy.rb" 26 | And the stdout should contain "dummy.erb" 27 | 28 | Scenario: Don't show the files that's not in .rstrip 29 | Given a file named ".rstrip" with: 30 | """ 31 | rb 32 | """ 33 | Given an empty file named "lib/dummy.rb" 34 | Given an empty file named "dummy.erb" 35 | When I run `rstrip config list` 36 | And the stdout should contain "lib/dummy.rb" 37 | And the stdout should not contain "dummy.erb" 38 | 39 | Scenario: Run rstrip should remove the last new lines 40 | Given a file named ".rstrip" with: 41 | """ 42 | rb 43 | """ 44 | Given a file named "lib/dummy.rb" with: 45 | """ 46 | def a 47 | puts 'hello' 48 | end 49 | 50 | 51 | """ 52 | When I run `rstrip process` 53 | Then the stdout should contain "process lib/dummy.rb" 54 | And a file named "lib/dummy.rb" should exist 55 | And the file "lib/dummy.rb" should contain exactly: 56 | """ 57 | def a 58 | puts 'hello' 59 | end 60 | """ -------------------------------------------------------------------------------- /lib/rstrip/rstrip.rb: -------------------------------------------------------------------------------- 1 | module Rstrip 2 | 3 | class Rstrip 4 | 5 | class << self 6 | 7 | def process(file_path) 8 | if File.symlink?(file_path) 9 | puts "skip symlink #{file_path}" 10 | return 11 | elsif !File.writable?(file_path) 12 | puts "skip read only #{file_path}" 13 | return 14 | elsif File.directory?(file_path) 15 | # Return quietly 16 | return 17 | else 18 | puts "process #{file_path}" 19 | end 20 | content = "" 21 | File.open(file_path, 'r') do |file| 22 | file.each_line do |line| 23 | content << rstrip(line) 24 | end 25 | end 26 | File.open(file_path, 'w') do |file| 27 | file.write(content.rstrip + "\n") 28 | end 29 | end 30 | 31 | def rstrip(line) 32 | line.rstrip + "\n" 33 | end 34 | 35 | def list 36 | if File.exists?("#{Dir.pwd}/.rstrip") 37 | path = "#{Dir.pwd}/.rstrip" 38 | puts "Using #{Dir.pwd}/.rstrip in the current directory" 39 | elsif File.exists?("#{Dir.home}/.rstrip") 40 | path ="#{Dir.home}/.rstrip" 41 | puts "Using #{Dir.home}/.rstrip in your home directory" 42 | else 43 | puts %{ Can't find any .rstrip config file\n 44 | Please run 'rstrip config generate'\n 45 | } 46 | exit 47 | end 48 | extensions = get_extensions(path) 49 | get_files(extensions) 50 | end 51 | 52 | private 53 | 54 | def get_extensions(path) 55 | extensions = [] 56 | file = File.open(path, "r") 57 | file.each_line do |line| 58 | line.strip! 59 | unless line.empty? 60 | if line.start_with?(".") 61 | line = line[1..-1] 62 | end 63 | extensions << line 64 | end 65 | end 66 | puts "Using the following extensions:\n #{extensions.join(', ') }\n" 67 | extensions 68 | end 69 | 70 | def get_files(extensions) 71 | pattern = "**/*.{#{extensions.join(",")}}" 72 | files = Dir.glob(pattern) 73 | puts "Files that will be operated on:" 74 | files.collect{|f| puts f} 75 | files 76 | end 77 | 78 | end # end class method 79 | 80 | end 81 | 82 | end 83 | --------------------------------------------------------------------------------