duraki/devist

View on GitHub
lib/devist/parser.rb

Summary

Maintainability
A
25 mins
Test Coverage
require 'date'

# Base class for extracting raw markdown file. Provides a method for extraction
# project info and changelog dataset. Checks for a proper devist format
# structure.
#
# @author Halis Duraki
class Devist::Parser

  # @return [Object] Project instance
  attr_reader :project

  # @return [Object] Changelog instance
  attr_reader :changelog

  # @return [Object] Change indexes
  attr_reader :indexes 

  TAGS = ["ADDED", "CHANGED", "FIXED", "REMOVED", "DEPRECATED", "SECURITY"]

  def initialize
    @indexes = {}
  end

  # Build and extract project details by fmm.
  #
  # @param [String] line to cmp to
  # @return [String] project detail
  def build_info(line)
    case line
    when /@project:+/
      @project.name = Devist::Extractor.extract_info(line) 
      print "  * Extracting project name       ...   [#{@project.name.strip!}]\n"
    when /@author:.+/
      @project.author = Devist::Extractor.extract_info(line)
      print "  * Extracting project author     ...   [#{@project.author.strip!}]\n"
    when /@homepage:.+/
      @project.homepage = Devist::Extractor.extract_info(line)
      print "  * Extracting project homepage   ...   [#{@project.homepage.strip!}]\n"
    end
  end

  # Build changelog version and changetags.
  #
  # @param [String] line to cmp to
  # @return [Object] built changelog
  def build_changelog(line, index)
    build_version(line)
    build_tags(line)
    build_tags_kac(line, index)
  end

  def read_change_of_index(i, type)
    i += 1 # => Always add index to /###/ match
    f = File.readlines(@filename).to_a

    while i.to_i < f.count.to_i
      return if f.at(i).to_s.match(/###.+/) # => Return match on next known tag
      next if f.at(i).to_s.empty? # => Return match on empty change
      @changelog[@version].tag type, Devist::Extractor.extract_change_kac(f.at(i.to_i))
      i+=1
    end
  end

  # Build changelog tags and changes index based on gnu/kac format.
  #
  # @param [String] line to cmp to
  # @param [Integer] line index
  # @return [Void] 
  def build_tags_kac(line, i)
    case line
    when /### Added/, /### Add/
      @indexes.store("added", i)
      read_change_of_index(@indexes["added"], 'added')
    when /### Changed/, /### Change/
      @indexes.store("changed", i)
      read_change_of_index(@indexes["changed"], 'changed')
    when /### Fixed/, /### Fix/
      @indexes.store("fixed", i)
      read_change_of_index(@indexes["fixed"], 'fixed')
    when /### Removed/, /### Remove/
      @indexes.store("removed", i)
      read_change_of_index(@indexes["removed"], 'removed')
    when /### Deprecated/, /### Deprecate/
      @indexes.store("deprecated", i)
      read_change_of_index(@indexes["deprecated"], 'deprecated')
    when /### Security/
      @indexes.store("security", i)
      read_change_of_index(@indexes["security"], 'security')
    end

    puts @indexes.sort_by {|_key, v| v}.to_h
  end

  def read_changes_from_to(i_start, i_stop)
    puts @filename 
    exit
  end

  # Build changelog tags and changes.
  #
  # @param [String] line to cmp to
  # @return [Object] changelog tag
  def build_tags(line)
    case line
    when /#added.+/ # => todo: /### Added/
      @changelog[@version].tag 'added', Devist::Extractor.extract_change(line)
    when /#changed.+/ 
      @changelog[@version].tag 'added', Devist::Extractor.extract_change(line)
    when /#fixed.+/
      @changelog[@version].tag 'fixed', Devist::Extractor.extract_change(line)
    when /#removed.+/
      @changelog[@version].tag 'removed', Devist::Extractor.extract_change(line)
    when /#deprecated.+/
      @changelog[@version].tag 'deprecated', Devist::Extractor.extract_change(line)
    when /#security.+/
      @changelog[@version].tag 'security', Devist::Extractor.extract_change(line)
    end
  end

  # Build changelog version.
  #
  # @param [String] line to cmp to
  # @return [Object] changelog version
  def build_version(line)
    case line
      when /\[[0-9]+.[0-9]+.[0-9]+]/ # => improved from: \[*.+]
      @date = Date.parse(line)
      @version += 1
      @changelog[@version] = Devist::Version.new (Devist::Extractor.extract_version_kac line), @date

      when /### Version+/
      @date = Date.parse(line) # Extract version date
      @version += 1 # Increment version
      @changelog[@version] = Devist::Version.new (Devist::Extractor.extract_version line), @date
    end
  end

  # Check for proper devist file structure.
  #
  # @param [String] file to validate
  # @return [Bool] proper file structure
  #
  # @deprecated devist is now being built to guess file structure
  def devist?(file_name)
    is_devist = File.open(file_name).to_a

    if is_devist.last.equal?("")
      is_devist.pop is_devist.last
    end

    print "  * Checking if changelog is devist configured ...\n"
    if is_devist.last.chomp != '.devist'
      print "  * The file is not configured for devist. Are you missing .devist at the end of the file?\n"
      print "  * Skipping ...\n"
    end

    print "  * Found .devist signature.\n"
  end

  # Parse given line and detect linechange.
  #
  # @param [String] file to parse
  # @return [Object] changelog data
  def parse_data(file_name)
    @project = Devist::Project.new
    @changelog = []
    @version = -1 # Start from 0
    @filename = file_name

    devist?(file_name) # Check if file is configured for usage

    print "  * Building model from file data ...\n"

    File.foreach(file_name).each_with_index do |line, i|
      build_info(line) # Build project info
      build_changelog(line, i) # Build changelog data
    end

    #puts @changelog[@version].inspect
    #l = File.open(@filename).to_a
    #puts l.at(@indexes[:added])
    #exit

    #@indexes.each_with_index do |t, j|
      #puts t,j
    #end
    #read_changes_from_to

    @changelog
  end

end

require 'devist/extractor'
require 'devist/models/project'
require 'devist/models/tags'
require 'devist/models/version'