简体   繁体   中英

How can I edit a ruby file (Rakefile) in place from within ruby?

I'm not sure if the question title makes sense, but here's what I'm trying to do.

I have a Rakefile that contains an array. I want to be able to use another ruby script to read the Rakefile, add something to that array, sort it, then write it back to the Rakefile in place.

In pseudo code, this is what I'm essentially trying to achieve:

rake_file = load file('Rakefile')
rake_file.array += 'new data'
rake_file.array.sort!
file.write Rakefile

The Rakefile contains many arrays and tasks, so I can't treat it like a regular text file and just append a value to the file and sort, hence why my idea is to load it and edit the array as above.

Is this even possible?

I can't treat it like a regular text file

You then need to learn ANTLR, create a Ruby grammar, generate a parser, and write a Java or C# or Python tree walker to edit your array. Simple :-)

I have imagined a quick and simple solution. The array is kept in a file, say array_source.rb :

    a = [1, 5, 10, 15]

This file can be manually edited, or, if you need to programmatically generate the data, created with a script, say create_array_source.rb :

# update the file containing the array of data in text representation

array_source_name = 'array_source.rb'

a = [1, 5, 10, 15]
# add new data
[2, 6, 11, 16].each { | e | a << e }
puts a.join(' ')

# Write it to a file
File.open(array_source_name, 'w') do | out |
    # to avoid a very long single line, the data is pretty printed
    groups = []
    a.sort.each_slice(4) { | slice | groups << slice.join(', ') }
    out.puts '    ['
    out.print '     '
    out.puts groups.join(",\n     ")
    out.puts '    ]'
end

puts "#{array_source_name} has been created"

Execution :

$ ruby -w create_array_source.rb 
1 5 10 15 2 6 11 16
array_source.rb has been created

File array_source.rb after :

    [
     1, 2, 5, 6,
     10, 11, 15, 16
    ]

In the Rakefile, the array to update is placed between two specific markers :

task :default => [:ta, :tb] do
end

task :ta do
    # $$insert array after$$
    a = [1, 5, 10, 15]
    # $$insert array before$$
    # do something with a
end

task :tb do
    # do something
end

So it is easy to write a script which processes it as a text file, splitting the lines into two parts :

  • from the beginning to the "insert after" marker
  • from the "insert before" marker to the end

and then rewrite the file by concatenating the first part, the array and the second part :

# modify a specific array in a Rakefile

rakefile_name     = 'Rakefile'
array_source_name = 'array_source.rb'
lines = IO.readlines(rakefile_name)
insert_marker_after_seen  = false
insert_marker_before_seen = false
lines1 = []
lines2 = IO.readlines(array_source_name)
lines3 = []

# split the Rakefile
lines.each do | line |
    case
    when insert_marker_after_seen == false
        lines1 << line

        if line.include?('$$insert array after$$')
        then
            insert_marker_after_seen = true
        end
    when ! insert_marker_before_seen
        # ignore array lines

        if line.include?('$$insert array before$$')
        then
            insert_marker_before_seen = true
            lines3 << line
        end
    else
        lines3 << line
    end
end

# Rewrite the Rakefile
File.open(rakefile_name, 'w') do | out |
    [ lines1, lines2, lines3 ].each do | lines_group |
        lines_group.each { | line | out.puts line }
    end
end

puts "#{rakefile_name} has been updated with #{array_source_name}"

Execution :

$ ruby -w modify_rakefile.rb 
Rakefile has been updated with array_source.rb

Rakefile after :

task :default => [:ta, :tb] do
end

task :ta do
    # $$insert array after$$
    [
     1, 2, 5, 6,
     10, 11, 15, 16
    ]
    # $$insert array before$$
    # do something with a
end

task :tb do
    # do something
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM