module Vedeu module Editor # A collection of keypresses ordered by input. # class Document include Vedeu::Repositories::Model extend Forwardable def_delegators :cursor, :ox, :oy, :x, :y # @!attribute [r] attributes # @return [Hash] attr_reader :attributes # @!attribute [rw] data # @return [String] attr_accessor :data # @!attribute [rw] name # @return [String|Symbol] attr_accessor :name # Returns a new instance of Vedeu::Editor::Document. # # @param attributes [Hash] # @option attributes data [String] # @option attributes name [String|Symbol] # @option attributes repository # [Vedeu::Repositories::Repository] # @return [Vedeu::Editor::Document] def initialize(attributes = {}) defaults.merge!(attributes).each do |key, value| instance_variable_set("@#{key}", value || defaults.fetch(key)) end end # Deletes the character from the line where the cursor is # currently positioned. # # @return [Vedeu::Editor::Document] def delete_character @lines = lines.delete_character(y, x - 1) left end # Delete a line. # # @return [Vedeu::Editor::Document] def delete_line @lines = lines.delete_line(y) up end # Returns the document as a string with line breaks if there is # more than one line. # # @return [String] def execute command = lines.map(&:to_s).join("\n") reset! Vedeu.trigger(:_clear_view_content_, name) Vedeu.trigger(:_command_, command) command end # Inserts the given character in to the line where the cursor is # currently positioned. # # @param character [String|Symbol] # @return [Vedeu::Editor::Document] def insert_character(character) return self if character.is_a?(Symbol) @lines = lines.insert_character(character, y, x) right end # Insert an empty line. # # @return [Vedeu::Editor::Document] def insert_line down @lines = lines.insert_line(Vedeu::Editor::Line.new, y) bol end # Returns the current line from the collection of lines. # # @return [Array] def line lines.line(y) end # Returns the collection of lines which constitutes the document # content. # # @return [Array] def lines @lines ||= Vedeu::Editor::Lines.coerce(data) end # Reset the document to the empty state. # # @return [Vedeu::Editor::Document] def reset! @cursor = cursor.reset! @lines = defaults[:data] refresh end # Store the document in the documents repository, clear and # send the content to the terminal. # # @return [Vedeu::Editor::Document] def refresh store Vedeu.trigger(:_clear_view_content_, name) Vedeu::Output::Output.render(output) cursor.refresh self end # Move the virtual cursor left. # # @return [Vedeu::Editor::Document] def left cursor.left refresh end # Move the virtual cursor right. # # @return [Vedeu::Editor::Document] def right cursor.right refresh end # Move the virtual cursor up. # # @return [Vedeu::Editor::Document] def up cursor.up refresh end # Move the virtual cursor down. # # @return [Vedeu::Editor::Document] def down cursor.down refresh end # Move the virtual cursor to the beginning of the line. # # @return [Vedeu::Editor::Document] def bol cursor.bol refresh end private # Returns the default options/attributes for this class. # # @return [Hash void|Symbol] def defaults { data: Vedeu::Editor::Lines.new([Vedeu::Editor::Line.new]), name: nil, repository: Vedeu.documents, } end # Return the data needed to render the document, based on the # current virtual cursor position. This output may be a cropped # representation of the full document depending on the size of # the interface. # # @return [Array] def output Vedeu::Editor::Cropper.new(lines: lines, name: name, ox: ox, oy: oy).viewport end # Return a virtual cursor to track the cursor position within # the document. # # @return [Vedeu::Editor::Cursor] def cursor @cursor ||= Vedeu::Editor::Cursor.new(name: name) end end # Document end # Editor end # Vedeu