Skip to content
Snippets Groups Projects
Action.cpp 5.77 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "Action.hpp"
    
    
    Action::Action(Action::Type type, std::function<void(Config & config, Action & action)> apply, std::function<void(Config & config, Action & action)> undo, std::function<bool(const Config & config, const Action & action)> appliable)
    
    {
      this->type = type;
      this->apply = apply;
      this->undo = undo;
      this->appliable = appliable;
    }
    
    Action Action::addLinesIfNeeded(int nbLines)
    {
      auto apply = [nbLines](Config & config, Action &)
      {
        config.addLines(1);
      };
    
      auto undo = [](Config &, Action &)
      {
      };
    
    
      auto appliable = [](const Config &, const Action &)
    
      {
        return true;
      };
    
      return {Type::AddLines, apply, undo, appliable};
    }
    
    Action Action::moveWordIndex(int movement)
    {
      auto apply = [movement](Config & config, Action &)
      {
        config.moveWordIndex(movement);
      };
    
      auto undo = [movement](Config & config, Action &)
      {
    
        config.moveWordIndex(-movement);
    
      auto appliable = [movement](const Config & config, const Action &)
    
        return config.canMoveWordIndex(movement);
    
      };
    
      return {Type::MoveWord, apply, undo, appliable};
    }
    
    Action Action::moveCharacterIndex(int movement)
    {
      auto apply = [movement](Config & config, Action &)
      {
        config.moveCharacterIndex(movement);
      };
    
      auto undo = [movement](Config & config, Action &)
      {
    
        config.moveCharacterIndex(-movement);
    
      auto appliable = [movement](const Config & config, const Action &)
    
        return config.canMoveCharacterIndex(movement);
    
      };
    
      return {Type::MoveChar, apply, undo, appliable};
    }
    
    
    Action Action::addHypothesis(const std::string & colName, std::size_t lineIndex, const std::string & hypothesis)
    {
      auto apply = [colName, lineIndex, hypothesis](Config & config, Action &)
      {
        config.getFirstEmpty(colName, lineIndex) = hypothesis;
      };
    
      auto undo = [colName, lineIndex](Config & config, Action &)
      {
        config.getLastNotEmpty(colName, lineIndex) = "";
      };
    
    
      auto appliable = [colName, lineIndex](const Config & config, const Action &)
    
      {
        return config.has(colName, lineIndex, 0);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    Action Action::addHypothesisRelative(const std::string & colName, Object object, int relativeIndex, const std::string & hypothesis)
    {
      auto apply = [colName, object, relativeIndex, hypothesis](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else
          lineIndex = config.getStack(relativeIndex);
    
    
    Franck Dary's avatar
    Franck Dary committed
        return addHypothesis(colName, lineIndex, hypothesis).apply(config, a);
    
      };
    
      auto undo = [colName, object, relativeIndex](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else
          lineIndex = config.getStack(relativeIndex);
    
        return addHypothesis(colName, lineIndex, "").undo(config, a);
      };
    
    
      auto appliable = [colName, object, relativeIndex](const Config & config, const Action & a)
    
      {
        int lineIndex = 0;
        if (object == Object::Buffer)
          lineIndex = config.getWordIndex() + relativeIndex;
        else if (config.hasStack(relativeIndex))
          lineIndex = config.getStack(relativeIndex);
        else
          return false;
    
        return addHypothesis(colName, lineIndex, "").appliable(config, a);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action Action::pushWordIndexOnStack()
    {
      auto apply = [](Config & config, Action &)
      {
        config.addToStack(config.getWordIndex());
      };
    
      auto undo = [](Config & config, Action &)
      {
        config.popStack();
      };
    
      auto appliable = [](const Config &, const Action &)
      {
        return true;
      };
    
      return {Type::Push, apply, undo, appliable}; 
    }
    
    Action Action::popStack()
    {
      auto apply = [](Config & config, Action & a)
      {
        auto toSave = config.getStack(0);
        a.data.push_back(std::to_string(toSave));
        config.popStack();
      };
    
      auto undo = [](Config & config, Action & a)
      {
        config.addToStack(std::stoi(a.data.back()));
      };
    
      auto appliable = [](const Config & config, const Action &)
      {
        return config.hasStack(0);
      };
    
      return {Type::Pop, apply, undo, appliable}; 
    }
    
    Action Action::attach(Object governorObject, int governorIndex, Object dependentObject, int dependentIndex)
    {
      auto apply = [governorObject, governorIndex, dependentObject, dependentIndex](Config & config, Action & a)
      {
        int lineIndex = 0;
        if (governorObject == Object::Buffer)
          lineIndex = config.getWordIndex() + governorIndex;
        else
          lineIndex = config.getStack(governorIndex);
        addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, config.getLastNotEmptyConst(Config::idColName, lineIndex)).apply(config, a);
      };
    
      auto undo = [governorObject, governorIndex, dependentObject, dependentIndex](Config & config, Action & a)
      {
        addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, "").undo(config, a);
      };
    
      auto appliable = [governorObject, governorIndex, dependentObject, dependentIndex](const Config & config, const Action & action)
      {
        int govLineIndex = 0;
        if (governorObject == Object::Buffer)
        {
          govLineIndex = config.getWordIndex() + governorIndex;
          if (!config.has(0, govLineIndex, 0))
            return false;
        }
        else
        {
          if (!config.hasStack(governorIndex))
            return false;
          govLineIndex = config.getStack(governorIndex);
        }
    
        return addHypothesisRelative(Config::headColName, dependentObject, dependentIndex, config.getLastNotEmptyConst(Config::idColName, govLineIndex)).appliable(config, action);
      };
    
      return {Type::Write, apply, undo, appliable}; 
    }
    
    
    Action::Object Action::str2object(const std::string & s)
    {
      if (s == "b")
        return Object::Buffer;
      if (s == "s")
        return Object::Stack;
    
      util::myThrow(fmt::format("Invalid object '{}'", s));
      return Object::Buffer;
    }