Indent spaces to tabs

Viewed 190

I really have problem reading code with spaces, so I use the visual studio code editor to indent codes from spaces to tabs before I read them.

But the problem is rails has a lot of files, I have to do the same operation repetitively. So, I want to use Dir.glob to iterate over all of them and covert spaces to tabs and overwrite those files. It is a terrible idea, but still...

Currently my String#spaces_to_tabs() method looks like this:

Code

# A method that works for now...
String.define_method(:spaces_to_tabs) do
    each_line.map do |x|
        match = x.match(/^([^\S\t\n\r]*)/)[0]
        m_len = match.length
        (m_len > 0 && m_len % 2 == 0) ? ?\t * (m_len / 2) + x[m_len .. -1] : x
    end.join
end

Which kind of works

Here's a test:

# Put some content that will get converted to space
content = <<~EOF << '# Hello!'
  def x
    'Hello World'
  end

  p x

  module X
    refine Array do
      define_method(:tally2) do
        uniq.reduce({}) { |h, x| h.merge!( x => count(x) ) }
      end
    end
  end

  using X
  [1, 2, 3, 4, 4, 4,?a, ?b, ?a].tally2
  p [1, 2, 3, 4, 4, 4,?a, ?b, ?a].tally2
  \r\r\t\t # Some invalid content
EOF

puts content.spaces_to_tabs

Output:

def x
    'Hello World'
end

p x

module X
    refine Array do
        define_method(:tally2) do
            uniq.reduce({}) { |h, x| h.merge!( x => count(x) ) }
        end
    end
end

using X
[1, 2, 3, 4, 4, 4,?a, ?b, ?a].tally2
p [1, 2, 3, 4, 4, 4,?a, ?b, ?a].tally2
         # Some invalid content
# Hello!

Currently it does not:

  1. Affect white-spaces (\t, \r, \n) other than spaces.
  2. Affect the output of code, only converts spaces to tabs.

I can't use my editor because:

  1. With Dir.glob (not included in this example), I can iterate over only .rb, .js, .erb, .html, .css, and .scss files.

Also, this is slow, but I can have at most 1000 files (above extensions) with 1000 lines of code for each file, but that's max, and not too practical, I generally have < 100 files with a couple of hundred lines of code. The code can take 10 seconds, which is not a problem here, since I need to run the code once for a project...

Is there a better way to do it?


Edit

Here's the full code with globbing for converting all major files in rails:

#!/usr/bin/ruby -w
String.define_method(:bold) { "\e[1m#{self}" }

String.define_method(:spaces_to_tabs) do
    each_line.map do |x|
        match = x.match(/^([^\S\t\n\r]*)/)[0]
        m_len = match.length
        (m_len > 0 && m_len % 2 == 0) ? ?\t * (m_len / 2) + x[m_len .. -1] : x
    end.join
end

GREEN = "\e[38;2;85;160;10m".freeze
BLUE = "\e[38;2;0;125;255m".freeze
TURQUOISE = "\e[38;2;60;230;180m".freeze
RESET = "\e[0m".freeze
BLINK = "\e[5m".freeze

dry_test = ARGV.any? { |x| x[/^\-(\-dry\-test|d)$/] }
puts "#{TURQUOISE.bold}:: Info:#{RESET}#{TURQUOISE} Running in Dry Test mode. Files will not be changed.#{RESET}\n\n" if dry_test

Dir.glob("{app,config,db,lib,public}/**/**.{rb,erb,js,css,scss,html}").map do |y|
    if File.file?(y) && File.readable?(y)
        read = IO.read(y)
        converted = read.spaces_to_tabs

        unless read == converted
            puts "#{BLINK}#{BLUE.bold}:: Converting#{RESET}#{GREEN} indentation to tabs of #{y}#{RESET}"
            IO.write(y, converted) unless dry_test
        end
    end
end
1 Answers

If this is just an intellectual exercise about tab indentation algorithms, then fine. If you really have trouble viewing the files, use Rubocop. It has configuration options that allow you to beautify the code, and the type of spaces it generates and the degree of indentation it applies. I use it with Atom and atom-beautify but I'm sure it has a plugin for VS code too. https://docs.rubocop.org/rubocop/0.86/cops_layout.html#layoutindentationconsistency

Related