Create hybrid authority model for command processing.
This commit is contained in:
		
							parent
							
								
									dbe6e437ad
								
							
						
					
					
						commit
						a73aa4feaf
					
				@ -5,54 +5,60 @@
 | 
			
		||||
#include <SDL3/SDL_events.h>
 | 
			
		||||
 | 
			
		||||
#include "client_network.h"
 | 
			
		||||
#include "command_processor.h"
 | 
			
		||||
#include "gfx/txt_renderer.h"
 | 
			
		||||
#include "vfs_manager.h"
 | 
			
		||||
#include "vfs.h"
 | 
			
		||||
#include "terminal.h"
 | 
			
		||||
 | 
			
		||||
Terminal::Terminal(void) {
 | 
			
		||||
  /* Placeholder welcome message to history. */
 | 
			
		||||
  _history.push_back("Welcome to Bettola");
 | 
			
		||||
  _network = new ClientNetwork();
 | 
			
		||||
  if(_network->connect("localhost", 8080)) {
 | 
			
		||||
    _history.push_back("Connection to server Success!");
 | 
			
		||||
  } else {
 | 
			
		||||
    _history.push_back("Connection to server failed!");
 | 
			
		||||
  }
 | 
			
		||||
  _current_path = "/";
 | 
			
		||||
  _history.push_back("Welcome to Bettola (local mode)");
 | 
			
		||||
  _network = nullptr; /* No network connection for now. */
 | 
			
		||||
 | 
			
		||||
  /* Create local file system for the client. */
 | 
			
		||||
  _local_vfs = vfs_manager::create_root_system();
 | 
			
		||||
  _local_cmd_processor = new CommandProcessor(_local_vfs);
 | 
			
		||||
  _current_path = get_full_path(_local_cmd_processor->get_current_dir());
 | 
			
		||||
  _scroll_offset = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Terminal::~Terminal(void) {
 | 
			
		||||
  delete _network;
 | 
			
		||||
  if(_network) {
 | 
			
		||||
    delete _network;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Terminal::_on_ret_press(void) {
 | 
			
		||||
  std::string command = _input_buffer;
 | 
			
		||||
  /* Add the command to history. */
 | 
			
		||||
  _history.push_back("> " + _input_buffer);
 | 
			
		||||
  _history.push_back(_current_path + "> " + command);
 | 
			
		||||
 | 
			
		||||
  /* For now, print the commmand clear buffer.
 | 
			
		||||
   * TODO: Parse and execute commands.
 | 
			
		||||
  std::string response;
 | 
			
		||||
  /*
 | 
			
		||||
   * All commands run locally for now.
 | 
			
		||||
   * TODO: Remote commands.
 | 
			
		||||
   */
 | 
			
		||||
  printf("Command entered: %s\n", _input_buffer.c_str());
 | 
			
		||||
  _network->send_command(_input_buffer.c_str());
 | 
			
		||||
  std::string response = _network->receive_response();
 | 
			
		||||
  if(command == "clear") {
 | 
			
		||||
    _history.clear();
 | 
			
		||||
  } else {
 | 
			
		||||
    response = _local_cmd_processor->process_command(command);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Check if the response is a new path for the prompt. */
 | 
			
		||||
  if(response.rfind("/", 0) == 0 && response.find('\n') == std::string::npos) {
 | 
			
		||||
  if(response.rfind("/", 0) == 0) {
 | 
			
		||||
    _current_path = response;
 | 
			
		||||
  } else if(!response.empty()) {
 | 
			
		||||
    /* Otherwise, it's command out. Split it by newline and add to history. */
 | 
			
		||||
    std::stringstream ss(response);
 | 
			
		||||
    std::string line;
 | 
			
		||||
    while(std::getline(ss, line, '\n')) {
 | 
			
		||||
      _history.push_back(line);
 | 
			
		||||
      if(!line.empty()) {
 | 
			
		||||
        _history.push_back(line);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(_input_buffer == "clear") {
 | 
			
		||||
    _history.clear();
 | 
			
		||||
  } else if(_input_buffer == "help") {
 | 
			
		||||
    _history.push_back("Commands: help, clear");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _input_buffer.clear();
 | 
			
		||||
  /* TODO: Ugly hack. Refactor to pass window height
 | 
			
		||||
   * We need the window height to know if we should
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,8 @@
 | 
			
		||||
 | 
			
		||||
#include "gfx/txt_renderer.h"
 | 
			
		||||
#include "client_network.h"
 | 
			
		||||
#include "vfs_manager.h"
 | 
			
		||||
#include "command_processor.h"
 | 
			
		||||
 | 
			
		||||
class Terminal {
 | 
			
		||||
public:
 | 
			
		||||
@ -22,5 +24,7 @@ private:
 | 
			
		||||
  std::vector<std::string> _history;
 | 
			
		||||
  int _scroll_offset;
 | 
			
		||||
  std::string _current_path;
 | 
			
		||||
  vfs_node* _local_vfs;
 | 
			
		||||
  CommandProcessor* _local_cmd_processor;
 | 
			
		||||
  ClientNetwork* _network;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								common/src/command_processor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								common/src/command_processor.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
#include "command_processor.h"
 | 
			
		||||
#include "vfs.h"
 | 
			
		||||
 | 
			
		||||
CommandProcessor::CommandProcessor(vfs_node* starting_dir) {
 | 
			
		||||
  _current_dir = starting_dir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vfs_node* CommandProcessor::get_current_dir(void) {
 | 
			
		||||
  return _current_dir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string CommandProcessor::process_command(const std::string& command) {
 | 
			
		||||
  if(command.rfind("cd ", 0) == 0) {
 | 
			
		||||
    std::string target_dir_name = command.substr(3);
 | 
			
		||||
    if(target_dir_name == "..") {
 | 
			
		||||
      if(_current_dir->parent) {
 | 
			
		||||
        _current_dir = _current_dir->parent;
 | 
			
		||||
      }
 | 
			
		||||
    } else if(_current_dir->children.count(target_dir_name)) {
 | 
			
		||||
      vfs_node* target_node = _current_dir->children[target_dir_name];
 | 
			
		||||
      if(target_node->type == DIR_NODE) {
 | 
			
		||||
        _current_dir = target_node;
 | 
			
		||||
      } else {
 | 
			
		||||
        return "cd: not a directory\n";
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      return "cd: no such file or directory\n";
 | 
			
		||||
    }
 | 
			
		||||
    return get_full_path(_current_dir);
 | 
			
		||||
  } else if(command == "ls") {
 | 
			
		||||
    std::string response = "";
 | 
			
		||||
    if(_current_dir && _current_dir->type == DIR_NODE) {
 | 
			
		||||
      for(auto const& [name, node] : _current_dir->children) {
 | 
			
		||||
        response += name;
 | 
			
		||||
        if(node->type == DIR_NODE) {
 | 
			
		||||
          response += "/";
 | 
			
		||||
        }
 | 
			
		||||
        response += "  ";
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return response;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return "Unknown command: " + command + "\n";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								common/src/command_processor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								common/src/command_processor.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "vfs.h"
 | 
			
		||||
 | 
			
		||||
class CommandProcessor {
 | 
			
		||||
public:
 | 
			
		||||
  CommandProcessor(vfs_node* starting_dir);
 | 
			
		||||
 | 
			
		||||
  std::string process_command(const std::string& command);
 | 
			
		||||
  vfs_node* get_current_dir(void);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  vfs_node* _current_dir;
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user