diff --git a/Changelog.md b/Changelog.md index e69de29..1b43ca9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -0,0 +1,3 @@ +1.0.0 +----- +* First release \ No newline at end of file diff --git a/License.md b/License.md index e307d80..a4fe192 100644 --- a/License.md +++ b/License.md @@ -1 +1 @@ - Este software puede ser utilizado sin cargo monetario(gratis) por el usuario. No se puede vender, no se puede obtener dinero de el. En el caso de que se distribuya públicamente por favor mencionarme como autor del mismo, gracias. IgorJorobus. \ No newline at end of file + This software can be used without monetary charge(free) by the user. Can not be sold, can't get money from it. In case you want to distribute it around please mention me, thank you. IgorJorobus. \ No newline at end of file diff --git a/Rakefile b/Rakefile index baa10ae..5fcb2ba 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +#encoding: utf-8 + #necesario para ejecutar los tests de minitest require 'rake/testtask' #necesario para ejecutar los tests de cucumber @@ -14,18 +16,12 @@ Rake::TestTask.new do |t| end #tarea para ejecutar los tests de cucumber con `cucumber` -Cucumber::Rake::Task.new do |t| - #opciones de cucumber a correr - t.cucumber_opts = %w{--format pretty --color} -end +Cucumber::Rake::Task.new #tarea para ejecutar cucumber wip(work in progress) con 'rake cucumber_wip' desc 'Ejecuta cucumber wip' task :cucumber_wip do - Cucumber::Rake::Task.new do |t| - #opciones de rspec a correr - t.rspec_opts = %w{--format pretty --color --wip @wip:3} - end + system('cucumber --format progress --color --wip --tags @wip:3') end #tarea para ejecutar todos los tests de rspec con `rake spec` @@ -39,3 +35,8 @@ task :rdoc do system('rdoc --all --tab-width=1 --format=darkfish --op=doc --force-output') end +desc 'Genera data/contenido_de_archivos.cocot' +task :generar_contenido_de_archivos do + require_relative('lib/cocot/salvador_de_contenidos') + SalvadorDeContenidos.new.salvar_contenido_de_archivos +end \ No newline at end of file diff --git a/ReadMe.md b/ReadMe.md index e69de29..92dc8ff 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -0,0 +1,63 @@ + cocot + ===== + + Sometimes you have a good 'no-rails' idea, and say for yourself: "what a good idea!", what mostly of the time is followed by "okay, but...I can't, I'm in many proyects and I had to create all the folder and files stuff, will take me 15 minutes, or more, so no". You are lazy and you know it. We are great builders of tools which makes our life easy, cocot is one of those. cocot is a very simple tool that puts you to work in one second, you just have to tell him which will be the name of your proyect and it's done, it creates you the structure of your **BDD** proyect. + + It supposes that you... + ----------------------- + + use RSpec and Cucumber for BDD developing, so it creates the conventional files and folders for work with. + + How can I use it? + ----------------- + + `cocot NameOfTheProyect` or `cocot "name of the proyect"`. Will build the skeleton in the current working directory, so be aware of be positioned where you want your proyect to be. + + Gemfile + ------- + + If you don't have **RSpec** and **Cucumber** installed on your system(or want to update them) you can do it by calling `bundle install` standing on the main folder of your proyect created by cocot. If you neither have **bundler** you will need to install it by calling `gem install bundler`. + + Rakefile + -------- + + cocot packs few pre-defined **rake** tasks: + + * `rake cucumber` : same like `cucumber` + * `rake cucumber_wip` : same like `cucumber --format progress --color --wip --tags @wip:3`, specially for order + * `rake spec` : same like `spec --color` + * `rake test` : run minitest tests + * `rake rdoc` : create a doc folder with **RDoc** documentation + + Skeleton + -------- + + cocot builds: + + bin\ + | proyect* + doc\ + features\ + | step_definitions\ + | support\ + | | env.rb + lib\ + | proyect* + | proyect*.rb + spec\ + | proyect* + | spec_helper.rb + Changelog.md + Gemfile + Gemfile.lock + License.md + Rakefile + ReadMe.md + + *proyect is replaced by the name of your proyect + + TODO + ---- + + * --full option. It builds you extra folders, like "Data", "Share", and "Test". + * --git-init option. Initialize a git repository(you will need to have **Git** in your system), and stash all the files created by cocot. \ No newline at end of file diff --git a/bin/cocot b/bin/cocot index 49ffd26..f0b7b6d 100644 --- a/bin/cocot +++ b/bin/cocot @@ -1 +1,4 @@ #!/usr/bin/env ruby +#encoding: utf-8 + +require_relative '../lib/cocot' \ No newline at end of file diff --git a/data/contenido_de_archivos.cocot b/data/contenido_de_archivos.cocot new file mode 100644 index 0000000..3a5bb47 --- /dev/null +++ b/data/contenido_de_archivos.cocot @@ -0,0 +1,58 @@ +{ :bin/proyectI"Y#!/usr/bin/env ruby +#encoding: utf-8 + +require_relative '../lib/name_of_the_proyect' +:ET:features/support/env.rbI"¿#encoding: utf-8 + +#if you respect the convention of a Ruby proyect layout then the next lines are fixed +$LOAD_PATH << File.expand_path('../../../lib', __FILE__) +require 'name_of_the_proyect' +;T:lib/proyect.rbI"#encoding: utf-8 +;T:spec/spec_helper.rbI"5#encoding: utf-8 + +require 'name_of_the_proyect' +;T: GemfileI"csource 'https://rubygems.org' + +gem 'rspec' +gem 'cucumber' +gem 'rake' +gem 'rdoc' +gem 'bundler' +;T: RakefileI"#encoding: utf-8 + +#necesary for minitest tests +require 'rake/testtask' +#necesary for cucumber tests +require 'cucumber/rake/task' +#necesary for rspec tests +require 'rspec/core/rake_task' + +#################TASKS####################### + +#to execute minitest tests with `rake test` +Rake::TestTask.new do |t| + #search recursively under the folder test for files called test*. You have to create the folder manually. + t.pattern = 'test/**/test*.rb' +end + +#to execute cucumber tests with `rake cucumber` +Cucumber::Rake::Task.new + +#to execute cucumber wip(work in progress) with 'rake cucumber_wip'. It will kick you if you are working in more than 3 scenarios +#remember to tag each wip scenarios with @wip above the Scenario keyword in the implicit *.feature +desc 'Executes cucumber wip' +task :cucumber_wip do + system('cucumber --format progress --color --wip --tags @wip:3') +end + +#to execute all RSpec tests with `rake spec` +RSpec::Core::RakeTask.new do |t| + #opciones de rspec a correr + t.rspec_opts = ['--color'] +end + +desc 'to generate RDoc documentation' +task :rdoc do + system('rdoc --all --tab-width=1 --format=darkfish --op=doc --force-output') +end +;T \ No newline at end of file diff --git a/features/cocot_construye_esqueleto.feature b/features/cocot_construye_esqueleto.feature new file mode 100644 index 0000000..f060db2 --- /dev/null +++ b/features/cocot_construye_esqueleto.feature @@ -0,0 +1,24 @@ +#language: es + +Característica: cocot construye el esqueleto del proyecto. + + Con el fin de cumplimentar el objetivo principal de la aplicación, + como desarrollador, + quiero poder lograr que cocot construya el esqueleto del nuevo proyecto en la ruta actual desde donde se está ejecutando la aplicación. + + @wip + Escenario: genero el árbol de carpetas. + Dado que el usuario ingresó correctamente el comando para esqueletizar su nuevo proyecto, por ejemplo: "cocot Proyecto", + Cuando origino sus carpetas, + Entonces debo encontrar creada una carpeta con nombre "Proyecto", + #realmente el step definition de la siguiente línea testea que estén todos los archivos también + Y dentro de ella debo encontrarme con la siguiente estructura de carpetas creadas: + | bin | + | lib | + | lib/Proyecto | + | spec | + | spec/Proyecto | + | features | + | features/support | + | features/step_definitions | + | doc | \ No newline at end of file diff --git a/features/step_definitions/cocot_construye_esqueleto_steps.rb b/features/step_definitions/cocot_construye_esqueleto_steps.rb new file mode 100644 index 0000000..849b647 --- /dev/null +++ b/features/step_definitions/cocot_construye_esqueleto_steps.rb @@ -0,0 +1,49 @@ +#encoding: utf-8 + +Dado(/^que el usuario ingresó correctamente el comando para esqueletizar su nuevo proyecto, por ejemplo: "cocot Proyecto",$/) do + cocot.limpiar_argumentos(['Proyecto']) + cocot.juzgar_argumentos + cocot.interrogar_juzgador + (cocot.instance_variable_get(:@error_existente).should_not be true) && (cocot.instance_variable_get(:@ayuda_invocada).should_not be true) +end + +Cuando(/^origino sus carpetas,$/) do + #si todo andubo bien, en el accionar se genera el esqueleto + cocot.accionar +end + +Entonces(/^debo encontrar creada una carpeta con nombre "Proyecto",$/) do + Dir.exists?("#{Dir.pwd}/#{nombre_del_proyecto()}").should be true +end + +Entonces(/^dentro de ella debo encontrarme con la siguiente estructura de carpetas creadas:$/) do |carpetas| + viejo_directorio_de_trabajo = Dir.pwd #: String + #me muevo una carpeta hacia adelante + Dir.chdir("./#{nombre_del_proyecto()}") + #tiene que haber lo siguiente + archivos_y_carpetas = %W{ Changelog.md + Gemfile + Gemfile.lock + License.md + Rakefile + ReadMe.md + bin + bin/#{nombre_del_proyecto()} + doc + features + features/step_definitions + features/support + features/support/env.rb + lib + lib/#{nombre_del_proyecto()} + lib/#{nombre_del_proyecto()}.rb + spec + spec/#{nombre_del_proyecto()} + spec/spec_helper.rb } + + Dir.glob('**/**/*').sort.should be === archivos_y_carpetas.sort + #vuelvo al viejo directorio de trabajo + Dir.chdir('..') + #elimino todas las carpetas y archivos creados + FileUtils.remove_dir("./#{nombre_del_proyecto}", true) +end diff --git a/features/step_definitions/usuario_ingresa_comando_steps.rb b/features/step_definitions/usuario_ingresa_comando_steps.rb new file mode 100644 index 0000000..4111141 --- /dev/null +++ b/features/step_definitions/usuario_ingresa_comando_steps.rb @@ -0,0 +1,64 @@ +#encoding: utf-8 + +#hooks del *.feature correspondiente +Around('@carpeta_existente') do |escenario, bloque| + directorio_implicito = 'Proyecto' + unless Dir.exists?(directorio_implicito) then Dir.mkdir(directorio_implicito) end + bloque.call + if Dir.exists?(directorio_implicito) then FileUtils.remove_dir(directorio_implicito, true) end +end + +Before do |escenario| + #en el modelo del dominio ::COCOT es utilizada. Apunta a la única instancia Cocot, la aplicación en si. + ::COCOT = cocot() +end + +#definiciones de pasos +Dado(/^que aún no inicié la aplicación,$/) do + cocot() +end + +Cuando(/^ejecuto el comando: "([^"]*)",$/) do |comando_ejecutado| + #extirpo la palabra 'cocot' venida del *.feature y otras + argumentos = comando_ejecutado.split.select {|palabra| (palabra.!=('cocot')) && (palabra.!=('\'\'')) && (palabra.!=('""'))} #: Array + #le digo a cocot que juzgue los argumentos pasados por el usuario al iniciar la aplicación + cocot.limpiar_argumentos(argumentos) + cocot.juzgar_argumentos +end + +Entonces(/^debo recibir en consola: "([^"]*)"[.,]$/) do |salida| + cocot.interrogar_juzgador + #el atributo salida es un #Array, cada item es un #String + cocot.instance_variable_get(:@salida).should include(salida.+("\n")) +end + +Entonces(/^a continuación: "([^"]*)", terminando el programa.$/) do |salida| + begin + cocot.accionar.should raise_error(SystemExit) + #cucumber falla si algún bloque levanta una excepción y no es rescatada, asi que... + rescue SystemExit + end +end + +Entonces(/^el programa debe terminarse\.$/) do + begin + cocot.accionar.should raise_error(SystemExit) + #cucumber falla si algún bloque levanta una excepción y no es rescatada, asi que... + rescue SystemExit + end +end + +Entonces(/^debo recibir en consola información que me ayude a comprender el funcionamiento de cocot,$/) do + cocot.interrogar_juzgador + cocot.instance_variable_get(:@ayuda_invocada).should be true +end + +Cuando(/^ejecuto el comando: "cocot 'Proyecto Fu Fu'", cocot entiende que el nombre del proyecto será "Proyecto Fu Fu",$/) do + #le digo a cocot que juzgue los argumentos pasados por el usuario al iniciar la aplicación + cocot.limpiar_argumentos(['Proyecto Fu Fu']) + cocot.juzgar_argumentos +end + +Dado(/^que existe la carpeta "([^"]*)" en el directorio actual,$/) do |carpeta| + Dir.exists?(carpeta).should be true +end \ No newline at end of file diff --git a/features/support/cocot_helpers.rb b/features/support/cocot_helpers.rb new file mode 100644 index 0000000..ef4967b --- /dev/null +++ b/features/support/cocot_helpers.rb @@ -0,0 +1,14 @@ +#encoding: utf-8 + +module CocotHelpers + + def cocot + @cocot ||= Cocot.new + end + + def nombre_del_proyecto + @nombre_del_proyecto ||= cocot.instance_variable_get(:@juzgador_de_argumentos).cual_será_el_nombre_del_proyecto? #: String + end +end + +World(CocotHelpers) \ No newline at end of file diff --git a/features/support/env.rb b/features/support/env.rb index 11aa432..c3d4439 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,25 +1,6 @@ #encoding: utf-8 -#keywords de cucumber en español(para que funcionen poner en la primera línea de cada *.feature "#language: es"): -=begin - "background": "Antecedentes", - "feature": "Característica", - "scenario": "Escenario", - "scenario_outline": "Esquema del escenario", - "examples": "Ejemplos", - "given": "*|Dado|Dada|Dados|Dadas", - "when": "*|Cuando", - "then": "*|Entonces", - "and": "*|Y", - "but": "*|Pero" -=end - -#plantilla para describir una característica: -=begin - En orden de - Como un/a - Quiero -=end +require 'fileutils' #si se respeta la convención del esqueleto de un proyecto en Ruby entonces la siguiente línea es fija $LOAD_PATH << File.expand_path('../../../lib', __FILE__) diff --git a/features/usuario_ingresa_comando.feature b/features/usuario_ingresa_comando.feature new file mode 100644 index 0000000..0f2f938 --- /dev/null +++ b/features/usuario_ingresa_comando.feature @@ -0,0 +1,49 @@ +#language: es + +Característica: el usuario ingresa un comando y obtiene una respuesta. + + Con el fin de conocer que sucede en la aplicación cuando ingreso determinado comando, + como usuario, + quiero poder ingresar un comando y recibir una respuesta. + + Antecedentes: la aplicación aún no fue iniciada. + Dado que aún no inicié la aplicación, + + #Casos erroneos. + + Esquema del escenario: intento iniciar la aplicación ingresando determinados comandos incorrectos. + Cuando ejecuto el comando: "", + Entonces debo recibir en consola: "", + Y el programa debe terminarse. + + Ejemplos: ingreso comandos incorrectos. + | comando | salida | + | cocot | Error: cocot needs to know the name of the further proyect. `cocot ''`. | + | cocot '' | Error: cocot needs to know the name of the further proyect. `cocot ''`. | + | cocot dos argumentos | Error: cocot just need one argument: the name of the further proyect. If its name have more than a word you must put these inside ''. | + | cocot --help nombre | Error: what do you want to do? invoke the help or skeletonize? You can't do both things. | + | cocot nombre del proyecto --help | Error: what do you want to do? invoke the help or skeletonize? You can't do both things. | + + @carpeta_existente + Escenario: ejecuto "cocot Proyecto" existiendo en el directorio actual una carpeta de nombre "Proyecto". + Dado que existe la carpeta "Proyecto" en el directorio actual, + Cuando ejecuto el comando: "cocot Proyecto", + Entonces debo recibir en consola: "Building skeletal structure for Proyecto.", + Y a continuación: "Skeletal structure can't be build. There's an existing folder in the working directory called Proyecto.", terminando el programa. + + #Solicitando ayuda. + + Escenario: invoco ayuda. + Cuando ejecuto el comando: "cocot --help", + Entonces debo recibir en consola información que me ayude a comprender el funcionamiento de cocot, + Y el programa debe terminarse. + + #Arrancando el programa satisfactoriamente. + + Escenario: arranco el programa satisfactoriamente. + Cuando ejecuto el comando: "cocot ProyectoFu", + Entonces debo recibir en consola: "Building skeletal structure for ProyectoFu.", + + Escenario: arranco el programa satisfactoriamente. + Cuando ejecuto el comando: "cocot 'Proyecto Fu Fu'", cocot entiende que el nombre del proyecto será "Proyecto Fu Fu", + Entonces debo recibir en consola: "Building skeletal structure for Proyecto Fu Fu.", \ No newline at end of file diff --git a/lib/cocot.rb b/lib/cocot.rb index e03771c..e70f885 100644 --- a/lib/cocot.rb +++ b/lib/cocot.rb @@ -2,4 +2,29 @@ #acá se requieren todos los archivos del código fuente, por ejemplo una línea podría ser "require 'cocot/archivo.rb'"... +require_relative 'cocot/cocot' +require_relative 'cocot/juzgador_de_argumentos' +require_relative 'cocot/salida_estandar' +require_relative 'cocot/constructor_de_esqueleto' +#ejecuto la aplicación +begin + #ejecuto lo siguiente solo si este archivo fue ejecutado desde 'cocot'. Evado que cucumber o rspec lo ejecuten. + if File.basename($0).==('cocot') + COCOT = Cocot.new + COCOT.limpiar_argumentos(ARGV) + COCOT.juzgar_argumentos + COCOT.interrogar_juzgador + COCOT.accionar + end +rescue => e + warn('###############################################################################################') + warn("ATTENTION: An exception of kind #{e.class} was raised by cocot with this message: #{e.message}.") + warn('This is the backtrace:') + e.backtrace.each do |trace| + warn(trace) + end + warn('###############################################################################################') + warn('Please provide me with this message in https://github.com/IgorJorobus/cocot/issues , thank you.') + warn('###############################################################################################') +end \ No newline at end of file diff --git a/lib/cocot/cocot.rb b/lib/cocot/cocot.rb new file mode 100644 index 0000000..5e916ac --- /dev/null +++ b/lib/cocot/cocot.rb @@ -0,0 +1,62 @@ +#encoding: utf-8 + +#Clase principal de la aplicación. +class Cocot + + attr_reader :salida + + def initialize + @salida = SalidaEstándar.new($stdout) + end + + #@param argumentos [Array]. Se quieren limpiar todos aquellos argumentos vacíos, como por ejemplo aquellos que surgen al pasar '' o "" en la línea de comandos. + def limpiar_argumentos(argumentos) + @argumentos = argumentos.select {|arg| arg.strip.length.!=(0)} #: Array + end + + #@param argumentos [Array]. + def juzgar_argumentos + @juzgador_de_argumentos = JuzgadorDeArgumentos.new #: JuzgadorDeArgumentos + @juzgador_de_argumentos.juzgar_argumentos(@argumentos) + end + + #Interroga al juzgador de argumentos en búsqueda de saber si hubo algún error en ellos. + def interrogar_juzgador + if @juzgador_de_argumentos.hubo_algun_error? + @error_existente = true + @salida.escribir(@juzgador_de_argumentos.describime_el_error) + elsif @juzgador_de_argumentos.fue_la_ayuda_solicitada? + @ayuda_invocada = true + mostrar_ayuda_en_pantalla() + else + @salida.escribir("Building skeletal structure for #{@nombre_del_proyecto = @juzgador_de_argumentos.cual_será_el_nombre_del_proyecto?}.\n") + end + end + + #El "accionar" de parte del programa se da una sola vez, luego del interrogatorio al juzgador. + def accionar + exit(false) if @error_existente + exit(true) if @ayuda_invocada + #llegado a este punto se entiende que el usuario ingresó correctamente el comando de inicio, aunqué puede que el constructor de esqueleto encuentre un problema + unless construir_esqueleto() then exit(false) end + #todo anduvo bien + true + end + + def construir_esqueleto + @constructor_de_esqueleto = ConstructorDeEsqueleto.new + #si la siguiente acción tiene éxito devuelve true, de otra forma false, lo cual quiere decir que hubo un problema + if @constructor_de_esqueleto.construir_esqueleto(@nombre_del_proyecto) + @salida.escribir("Structure builded. Have fun developing! :)\n") + true + else + @salida.escribir(@constructor_de_esqueleto.explicar_inconveniente) + false + end + end + + def mostrar_ayuda_en_pantalla + msj_de_ayuda = "cocot builds the skeleton layout of your BDD proyects. You just have to give him the name of your proyect like this: `cocot \"name of the proyect\"`.\n" + @salida.escribir(msj_de_ayuda) + end +end \ No newline at end of file diff --git a/lib/cocot/constructor_de_esqueleto.rb b/lib/cocot/constructor_de_esqueleto.rb new file mode 100644 index 0000000..9bd3334 --- /dev/null +++ b/lib/cocot/constructor_de_esqueleto.rb @@ -0,0 +1,80 @@ +#encoding: utf-8 + +#Una instancia de esta clase es la encargada de construir el esqueleto del nuevo proyecto. +class ConstructorDeEsqueleto + + attr_reader :inconveniente + + #todo lo que sea 'proyect' debe ser reemplazado por el nombre original del proyecto + SUBCARPETAS = %w{bin lib lib/proyect spec spec/proyect features features/support features/step_definitions doc} + ARCHIVOS = %w{Changelog.md Gemfile Gemfile.lock License.md Rakefile ReadMe.md bin/proyect features/support/env.rb lib/proyect.rb spec/spec_helper.rb} + + #@param nombre_del_proyecto [String]. @return [TrueClass or FalseClass]. + def construir_esqueleto(nombre_del_proyecto) + @nombre_del_proyecto = nombre_del_proyecto + if !(existe_carpeta_de_mismo_nombre_que_este_proyecto_en_el_directorio_actual?) + crear_carpeta_del_proyecto() + else + @inconveniente = "Skeletal structure can't be build. There's an existing folder in the working directory called #{@nombre_del_proyecto}.\n" + return false + end + #me voy a pasar a la carpeta creada + @directorio_de_trabajo_original = Dir.pwd #: String + Dir.chdir("./#{@nombre_del_proyecto}") + #ahí mismo creo el resto de las carpetas + crear_subcarpetas() + crear_archivos() + escribir_archivos() + #vuelvo al directorio original + Dir.chdir(@directorio_de_trabajo_original) + #si todo anduvo bien devuelvo true + true + end + + def crear_carpeta_del_proyecto + #creo la carpeta principal + Dir.mkdir(@nombre_del_proyecto) + #le digo a la aplicación que escriba en la salida un progreso + ::COCOT.salida.escribir('.') + end + + def crear_subcarpetas + SUBCARPETAS.collect {|carpeta| if carpeta.include?('proyect') then carpeta.sub('proyect', @nombre_del_proyecto) else carpeta end}.each do |carpeta| + Dir.mkdir(carpeta) + ::COCOT.salida.escribir('.') + end + end + + def crear_archivos + ARCHIVOS.collect {|archivo| if archivo.include?('proyect') then archivo.sub('proyect', @nombre_del_proyecto) else archivo end}.each do |archivo| + File.new(archivo, 'w+').close + ::COCOT.salida.escribir('.') + end + ::COCOT.salida.escribir("\n") + end + + def escribir_archivos + obtener_contenido_de_archivos() #: Hash + @contenido_de_archivos.each_pair do |nombre_del_archivo, contenido| + File.open(nombre_del_archivo.to_s.sub('proyect', @nombre_del_proyecto), 'w+b') do |archivo| + archivo.write(contenido.gsub('name_of_the_proyect', @nombre_del_proyecto)) + end + end + end + + def existe_carpeta_de_mismo_nombre_que_este_proyecto_en_el_directorio_actual? + Dir.exists?("./#{@nombre_del_proyecto}") + end + + def explicar_inconveniente + @inconveniente || "No hubo inconvenientes.\n" + end + + private + + def obtener_contenido_de_archivos + File.open(File.expand_path('../../../data/contenido_de_archivos.cocot', __FILE__), 'r+b') do |archivo| + @contenido_de_archivos = Marshal.load(archivo) #: Hash + end + end +end \ No newline at end of file diff --git a/lib/cocot/contenido_de_archivos.rb b/lib/cocot/contenido_de_archivos.rb new file mode 100644 index 0000000..5a7d53f --- /dev/null +++ b/lib/cocot/contenido_de_archivos.rb @@ -0,0 +1,86 @@ +#encoding: utf-8 + +module COCOT; end + +COCOT::CONTENIDO_DE_ARCHIVOS = {} + +COCOT::CONTENIDO_DE_ARCHIVOS[:'bin/proyect'] = \ +<'`.\n", \ + dos_o_mas_argumentos_como_nombre: "Error: cocot just need one argument: the name of the further proyect. If its name have more than a word you must put these inside ''.\n", \ + ayuda_y_esqueletizado_invocados_a_la_vez: "Error: what do you want to do? invoke the help or skeletonize? You can't do both things.\n"} + + #@param argumentos [Array]. + def juzgar_argumentos(argumentos) + if argumentos.length.==(0) + @error_presente_en_argumentos = :ningun_argumento #: Symbol + elsif ((argumentos.length).!=(cantidad_de_argumentos_sin_help = (argumentos.select {|arg| arg.!=('--help')}.length))) && (argumentos.!=(['--help'])) + @error_presente_en_argumentos = :ayuda_y_esqueletizado_invocados_a_la_vez + elsif cantidad_de_argumentos_sin_help.>(1) + @error_presente_en_argumentos = :dos_o_mas_argumentos_como_nombre + elsif argumentos[0].==('--help') + @ayuda_solicitada = true + else + @nombre_del_proyecto = argumentos[0] + end + end + + def hubo_algun_error? + true if @error_presente_en_argumentos + end + + def describime_el_error + if hubo_algun_error? + return ERRORES_CONOCIDOS[@error_presente_en_argumentos] + end + end + + def fue_la_ayuda_solicitada? + if @ayuda_solicitada then true else false end + end + + def cual_será_el_nombre_del_proyecto? + @nombre_del_proyecto || "No fue definido.\n" + end +end \ No newline at end of file diff --git a/lib/cocot/salida_estandar.rb b/lib/cocot/salida_estandar.rb new file mode 100644 index 0000000..a21795f --- /dev/null +++ b/lib/cocot/salida_estandar.rb @@ -0,0 +1,15 @@ +#encoding: utf-8 + +class SalidaEstándar < Array + + #@param salida [IO]. Inicializa la salida estándar de la aplicación. + def initialize(salida) + @salida = salida + end + + #@param texto [String]. Escribe determinado *texto* en la @salida. + def escribir(texto) + self.<<(texto) + @salida.print(texto) + end +end \ No newline at end of file diff --git a/lib/cocot/salvador_de_contenidos.rb b/lib/cocot/salvador_de_contenidos.rb new file mode 100644 index 0000000..9eabc0c --- /dev/null +++ b/lib/cocot/salvador_de_contenidos.rb @@ -0,0 +1,20 @@ +#encoding: utf-8 + +require_relative 'contenido_de_archivos' + +#Clase solo utilizada para el desarrollo de cocot. +class SalvadorDeContenidos + + #Genera ./data/contenido_de_archivos.cocot , un archivo binario con el contenido de los contenidos que tendrán los archivos generados por cocot. + def salvar_contenido_de_archivos + puts "Creando carpeta data si no existe." + unless Dir.exists?('data') then Dir.mkdir('data') end + puts "Creando contenido_de_archivos.cocot." + File.open('data/contenido_de_archivos.cocot', 'w+b') do |archivo| + Marshal.dump(COCOT::CONTENIDO_DE_ARCHIVOS, archivo) + end + puts "Creado." + end +end + + diff --git a/spec/cocot/cocot_spec.rb b/spec/cocot/cocot_spec.rb new file mode 100644 index 0000000..ce45543 --- /dev/null +++ b/spec/cocot/cocot_spec.rb @@ -0,0 +1,63 @@ +#encoding: utf-8 + +require 'spec_helper' + + +describe Cocot do + + it 'extrae los argumentos que considera útiles' do + argv = [' ', 'argumento_1', 'argumento_2'] + subject.limpiar_argumentos(argv).should be == ['argumento_1', 'argumento_2'] + end + + before(:each) do + ::COCOT = subject() + @argv = ['Nombre de la aplicación'] + subject.limpiar_argumentos(@argv) + end + + it 'crea un JuzgadorDeArgumentos' do + subject.juzgar_argumentos + subject.instance_variable_get(:@juzgador_de_argumentos).should_not be_nil + end + + it 'manda a juzgar los argumentos proveidos por el usuario' do + #si no hay error devuelve el nombre de la aplicación + subject.juzgar_argumentos.should be @argv[0] + end + + it 'interroga al juzgador preguntándole cual fue el resultado del juicio de argumentos' do + subject.juzgar_argumentos + subject.interrogar_juzgador + subject.instance_variable_get(:@salida).should include("Building skeletal structure for Nombre de la aplicación.\n") + end + + it 'acciona mediante comenzar a construir el esqueleto si los argumentos fueron correctos' do + subject.juzgar_argumentos + subject.interrogar_juzgador + subject.accionar.should be true + #elimino la carpeta generada al llamar accionar() + if Dir.exists?(dir = "./#{@argv[0]}") then FileUtils.remove_dir(dir, true) end + end + + before(:each) {} + + it 'muestra ayuda en pantalla si el usuario hizo correctamente la petición' do + argv = ['--help'] + subject.limpiar_argumentos(argv) + subject.juzgar_argumentos + subject.should_receive(:mostrar_ayuda_en_pantalla) + subject.interrogar_juzgador + end + + it 'acciona mediante salir de la aplicación si los argumentos no fueron correctos' do + begin + argv = ['argumentos', 'no', 'correctos'] + subject.limpiar_argumentos(argv) + subject.juzgar_argumentos + subject.interrogar_juzgador + subject.accionar.should raise_error(SystemExit) + rescue SystemExit + end + end +end \ No newline at end of file diff --git a/spec/cocot/juzgador_de_argumentos_spec.rb b/spec/cocot/juzgador_de_argumentos_spec.rb new file mode 100644 index 0000000..6383070 --- /dev/null +++ b/spec/cocot/juzgador_de_argumentos_spec.rb @@ -0,0 +1,70 @@ +#encoding: utf-8 + +require 'spec_helper' + + +describe JuzgadorDeArgumentos do + describe '#juzgar_argumentos' do + it 'reconoce si ningún argumento le fue pasado' do + subject.juzgar_argumentos([]).should be :ningun_argumento + end + + it 'reconoce si se intento invocar ayuda y a la vez se pasaron mas argumentos' do + subject.juzgar_argumentos(['--help', 'Proyecto']).should be :ayuda_y_esqueletizado_invocados_a_la_vez + end + + it 'reconoce si se pasaron mas de un argumento como nombre del proyecto' do + subject.juzgar_argumentos(['Dos', 'Nombres']).should be :dos_o_mas_argumentos_como_nombre + end + + it 'reconoce cuando la ayuda fue invocada correctamente' do + subject.juzgar_argumentos(['--help']).should be true + end + + it 'reconoce si no hubo error alguno' do + subject.juzgar_argumentos(['Proyecto']).should be_an_instance_of(String) + end + end + + context 'luego de juzgar argumentos' do + it 'sabe si hubo algún error' do + subject.juzgar_argumentos(['A', 'B']) + subject.hubo_algun_error?.should be true + end + + it 'y describirlo' do + subject.juzgar_argumentos(['--help', 'A', 'A']) + subject.describime_el_error.should be_an_instance_of(String) + end + + it 'sabe si no lo hubo' do + subject.juzgar_argumentos(['Nombre']) + subject.hubo_algun_error?.should be nil + end + + it 'si no hubo no puede describirlo' do + subject.juzgar_argumentos(['Nombre bien pasado']) + subject.describime_el_error.should be nil + end + + it 'responde si la ayuda fue solicitada' do + subject.juzgar_argumentos(['--help']) + subject.fue_la_ayuda_solicitada?.should be true + end + + it 'o no' do + subject.juzgar_argumentos(['Nombre']) + subject.fue_la_ayuda_solicitada?.should be false + end + + it 'dice cual es el nombre del proyecto si es que fue definido en el argumento' do + subject.juzgar_argumentos(['Secreto']) + expect {subject.cual_será_el_nombre_del_proyecto?}.to be {'Secreto'} + end + + it 'si no fue definido lo expresa' do + subject.juzgar_argumentos([]) + expect {subject.cual_será_el_nombre_del_proyecto?}.to be {'No fue definido'} + end + end +end \ No newline at end of file diff --git a/spec/cocot/salida_estandar_spec.rb b/spec/cocot/salida_estandar_spec.rb new file mode 100644 index 0000000..86f002d --- /dev/null +++ b/spec/cocot/salida_estandar_spec.rb @@ -0,0 +1,28 @@ +#encoding: utf-8 + +require 'spec_helper' + + +describe SalidaEstándar do + + before(:each) do + @texto = 'texto' + #emulo $stderr + @stderr = double('stderr').as_null_object + end + + describe '#escribir' do + it 'escribe texto en $stderr' do + @stderr.should_receive(:print).with(@texto) + #creo el subject + se = SalidaEstándar.new(@stderr) + se.escribir(@texto) + end + + it 'almacena el texto en si misma(es un #Array)' do + se = SalidaEstándar.new(@stderr) + se.escribir(@texto) + se.should include('texto') + end + end +end \ No newline at end of file