#
# CommandLineActions.rb
#
#   $Author: hiroya $
#   $Date: 2000/11/23 01:53:10 $
#   Copyright (C) 2000 Hiroya KUBO
#

class CommandLineActionException < Exception
  def initialize(value = "")
    @value = value
  end
  def getValue
    return @value
  end
end

class ExitCommandLineEditor < CommandLineActionException; end
class ContinueCompositeKeyStroke < CommandLineActionException; end
class EndCommandLineEditor < CommandLineActionException; end

require "StringUtil"

module CommandLineActions

  def self_insert_command
    c = @ctx.getCurrentChar
    if(c != nil)
      @line.insert(c)
      @term.print(c)
      @term.rewind
      showPrompt
    else
      @term.beep
    end
  end

  def default_command
    @term.beep
    #    @term.print("<#{@currentChar}>")
  end

  def sequence_read_in
    raise ContinueCompositeKeyStroke
  end

  def tty_sigintr
    raise ExitCommandLineEditor
  end

  def up_history
    if(@ctx.isCurrentEditingHistory?)
      @ctx.setCurrentEditingHistory(@line.getValue)
    end
    rotate_history(-1)
  end

  def down_history
    rotate_history(1)
  end

  def newline
    @term.newline
    raise EndCommandLineEditor
  end
  
  def complete_word
    key = @line.getCurrentWord
    list = getCompletingList(key)
    if(list != nil && list.size > 0)
      candidate = StringUtil.getSharedPrefix(list)
      if(candidate != nil && candidate != "")
	@line.insert(candidate)
	@term.cleanupCurrentLine
	showPrompt
      else
	@term.beep
      end
    else
      @term.beep
    end
  end

  def delete_char_or_list_or_eof
    if(! @line.end_of_line?)
      @line.remove(@line.getCursorPosition, @line.getCursorPosition+1)
      @term.cleanupCurrentLine
      showPrompt
    else
      key = @line.getCurrentWord
      list = getCompletingList(key)
      if(list != nil)
	@term.newline
	showCompletingList(list)
	showPrompt
      end
    end
  end

  def is_undefined
    @term.beep
  end

  def backward_delete_char
    if(! @line.remove(@line.getCursorPosition-1, @line.getCursorPosition) )
      @term.beep
    else
      @term.cleanupCurrentLine
      showPrompt
    end
  end

  def kill_line
    @ctx.storeYank(@line.kill_line)
    @term.cleanupCurrentLine
    showPrompt
  end

  def kill_whole_line
    @line.setCursorPosition(0)
    kill_line
  end

  def yank_backward
    @ctx.moveYankHistoryOffset(-1)
    str = @ctx.getYank(@ctx.getYankHistoryOffset)
    if (str != nil)
      @line.insert(str)
      @term.cleanupCurrentLine
      showPrompt
    else
      @term.beep
    end
  end

  def yank
    str = @ctx.getYank(@ctx.getYankHistoryOffset)
    if (str != nil)
      @line.insert(str)
      @term.cleanupCurrentLine
      showPrompt
    else
      @term.beep
    end
  end

  def set_mark_command
    @line.setMark
  end

  def kill_region
    if( @line.getMark != nil)
      if(@line.getMark < @line.getCursorPosition)
	@ctx.storeYank(@line.remove(@line.getMark, @line.getCursorPosition))
      else
	@ctx.storeYank(@line.remove(@line.getCursorPosition, @line.getMark))
      end
      @line.setMark(nil)
      @term.cleanupCurrentLine
      showPrompt
    else
      @term.beep
    end
  end

  def copy_region
    if( @line.getMark != nil)
      if(@line.getMark < @line.getCursorPosition)
	@ctx.storeYank(@line.copy(@line.getMark, @line.getCursorPosition))
      else
	@ctx.storeYank(@line.copy(@line.getCursorPosition, @line.getMark))
      end
      @line.setMark(nil)
    else
      @term.beep
    end
  end

  def beginning_of_line
    @line.setCursorPosition(0)
    @term.rewind
    showPrompt
  end

  def end_of_line
    @line.setCursorPositionToEnd
    @term.rewind
    showPrompt
  end

  def forward_char
    move_char(1)
  end

  def backward_char
    move_char(-1)
  end

  def clear_screen
    @term.cleanupCurrentLine
    showPrompt
  end

  def rotate_history(n)
    if(@ctx.browseEditingHistory(n) != nil)
      @line.setValue(@ctx.getCurrentEditingHistory)
      @line.setCursorPositionToEnd
      @term.cleanupCurrentLine
      showPrompt
    else
      @term.beep
    end
  end
  private :rotate_history

  def move_char(n)
    if(! @line.moveCursor(n))
      @term.beep
    else
      @term.rewind
      showPrompt
    end
  end
  private :move_char

end
