2017-10-21 39 views
0

Je ne suis pas sûr si le titre de la question est logique, mais voici ce que je suis en train de faire.Comment puis-je modifier un fichier ruby ​​(Rakefile) à partir de ruby?

J'ai un Rakefile qui contient un tableau. Je veux pouvoir utiliser un autre script ruby ​​pour lire le Rakefile, ajouter quelque chose à ce tableau, le trier, puis l'écrire dans le Rakefile en place.

Dans le code pseudo, c'est ce que je suis essentiellement d'essayer d'atteindre:

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

Le Rakefile contient de nombreux tableaux et tâches, donc je ne peux pas le traiter comme un fichier texte normal et juste ajouter une valeur pour le fichier et le tri, d'où la raison pour laquelle mon idée est de le charger et d'éditer le tableau comme ci-dessus.

Est-ce encore possible?

Répondre

0

Je ne peux pas le traiter comme un fichier texte normal

Vous devez ensuite apprendre ANTLR, créer une grammaire Ruby, générer un analyseur, et écrire un Java ou une marchette C# ou arbre Python éditez votre tableau. Simple :-)

J'ai imaginé une solution rapide et simple. Le tableau est conservé dans un fichier, par exemple array_source.rb:

a = [1, 5, 10, 15] 

Ce fichier peut être modifié manuellement ou, si vous avez besoin pour générer les données par programmation, créées à l'aide d'un script, dire 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" 

exécution:

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

fichier array_source.rb après:

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

Dans le Rakefile, le tableau de mise à jour est placé entre deux marqueurs spécifiques:

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 

Il est donc facile d'écrire un script qu'il traite comme un fichier texte, diviser les lignes en deux parties:

  • dès le début de la « insérer après » marqueur
  • de la « insérer avant » marqueur à l'extrémité

puis réécrire le fichier en concaténant la première partie, le tableau et la deuxième partie:

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

Exécution:

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

Rakefile après:

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 
+0

J'aime l'idée, Cependant, cela ne résout pas le problème de garder le tableau trié et encombrera également le Rakefile avec des marqueurs.Qu'en est-il peut-être de charger le rakefile en mémoire, d'éditer le tableau après sa lecture, puis de réécrire le fichier dans son intégralité? – sum1quiet

+0

J'ai passé 4 heures à préparer cette réponse. Est-ce que vous l'avez vu ? Le tableau EST trié dans 'create_array_source.rb', dans' File.open ... 'par' a.sort ... '. Le Makefile EST chargé en mémoire: 'lines = IO.readlines (rakefile_name)'. Le fichier est réécrit dans son intégralité. Comment voulez-vous éditer le tableau sans analyser le code Ruby avec un parseur ou utiliser l'astuce du marqueur? Vous pouvez utiliser 'if line.include? ('')', mais le tableau doit avoir un nom/une position unique. Je vous laisse imaginer d'autres solutions. – BernardK

+0

Mon erreur, j'ai mal lu l'ordre de celui-ci. Merci pour vos efforts à ce sujet, je vais certainement essayer. – sum1quiet