Как я могу отредактировать файл ruby ​​(Rakefile) на месте изнутри ruby?

Я не уверен, имеет ли смысл название вопроса, но вот что я пытаюсь сделать.

У меня есть Rakefile, который содержит массив. Я хочу использовать другой скрипт ruby ​​для чтения файла Rakefile, добавления чего-либо в этот массив, сортировки, а затем записи его обратно в файл Rake на месте.

В псевдокоде это то, чего я пытаюсь достичь:

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

Rakefile содержит много массивов и задач, поэтому я не могу рассматривать его как обычный текстовый файл, просто добавить значение в файл и отсортировать, поэтому моя идея состоит в том, чтобы загрузить его и отредактировать массив, как указано выше.

Это вообще возможно?

1 ответ

Решение

Я не могу рассматривать это как обычный текстовый файл

Затем вам нужно изучить ANTLR, создать грамматику Ruby, сгенерировать синтаксический анализатор и написать обходчик дерева Java или C# или Python для редактирования массива. Просто:-)

Я придумал быстрое и простое решение. Массив хранится в файле, скажем array_source.rb:

    a = [1, 5, 10, 15]

Этот файл можно редактировать вручную или, если вам нужно программно сгенерировать данные, созданные с помощью скрипта, например, 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"

Исполнение:

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

Файл array_source.rb после:

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

В Rakefile массив для обновления помещается между двумя конкретными маркерами:

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

Поэтому легко написать скрипт, который обрабатывает его как текстовый файл, разбивая строки на две части:

  • от начала до маркера "вставить после"
  • от маркера "вставить до" до конца

а затем переписать файл путем объединения первой части, массива и второй части:

# 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}"

Исполнение:

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

Рейкфайл после:

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
Другие вопросы по тегам