Skip to content

Commit

Permalink
Tab Completion
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzom222 committed Jul 23, 2023
1 parent 9b853db commit d97df98
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 64 deletions.
19 changes: 19 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"macFrameworkPath": [
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/local/bin/g++-13",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64"
}
],
"version": 4
}
Empty file added requirements.txt
Empty file.
Binary file modified stugrad
Binary file not shown.
196 changes: 132 additions & 64 deletions stugrad.cpp
Original file line number Diff line number Diff line change
@@ -1,82 +1,150 @@
#include <cstdlib> // for system()
#include <cstring> // for strcmp()
#include <cstdlib> // for system()
#include <cstring> // for strcmp()
#include <dirent.h> // for opendir(), readdir(), closedir()
#include <iostream> // for std::cin, std::cout
#include <readline/history.h>
#include <readline/readline.h>
#include <sstream> // for std::istringstream
#include <string> // for std::string, std::getline
#include <string> // for std::string, std::getline
#include <vector>

class CommandLineInterface {
public:
void run() {
while (true) {
std::cout << "> ";
std::string line;
if (!std::getline(std::cin, line)) {
break;
}
if (line.empty()) {
continue;
}
if (line == "quit" || line == "exit") {
break;
}
std::string command;
std::string assignment;
if (!parse_command_line(line, command, assignment)) {
continue;
}
if (command == "-m" || command == "--multi-grader") {
run_multi_grader(assignment);
} else {
std::cerr << "myprogram: invalid command\n";
print_help();
}
}
CommandLineInterface() {
// Initialize Readline library
rl_attempted_completion_function = completion;
}

void run() {
while (true) {
// Use Readline to read user input with tab completion
char *input = readline("> ");
if (!input) {
break;
}
std::string line(input);
free(input);

if (line.empty()) {
continue;
}
if (line == "quit" || line == "exit") {
break;
}
std::string command;
std::string assignment;
if (!parse_command_line(line, command, assignment)) {
continue;
}
if (command == "-m" || command == "--multi-grader") {
run_multi_grader(assignment);
} else {
std::cerr << "myprogram: invalid command\n";
print_help();
}
}
}

private:
void print_help() const {
std::cout << "Usage: myprogram [options]\n";
std::cout << "\n";
std::cout << "Options:\n";
std::cout << " -h, --help Show this help message and exit\n";
std::cout << " -m, --multi-grader ASSIGNMENT\n";
std::cout << " Grade the specified assignment using multi-grader\n";
static char **completion(const char *text, int start, int end) {
// Generate completion matches
rl_attempted_completion_over = 1;
return rl_completion_matches(text, generator);
}

static char *generator(const char *text, int state) {
static int index;
static std::vector<std::string> matches;

if (state == 0) {
index = 0;
matches.clear();

// Check if the user is entering the ASSIGNMENT argument
if (rl_point > 0 && rl_line_buffer[rl_point - 1] == ' ') {
// Generate a list of possible directory completion matches
std::string path(text);
std::size_t pos = path.find_last_of('/');
if (pos != std::string::npos) {
path = path.substr(0, pos + 1);
} else {
path.clear();
}
DIR *dir = opendir(path.empty() ? "." : path.c_str());
if (dir) {
struct dirent *entry;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_type == DT_DIR &&
std::strncmp(text + path.size(), entry->d_name,
strlen(text) - path.size()) == 0) {
matches.push_back(path + entry->d_name);
}
}
closedir(dir);
}
} else {
// Generate a list of possible command completion matches
if (std::strncmp(text, "-m", strlen(text)) == 0) {
matches.push_back("-m");
}
if (std::strncmp(text, "--multi-grader", strlen(text)) == 0) {
matches.push_back("--multi-grader");
}
}
}

void run_multi_grader(const std::string& assignment) const {
std::string command = "./multi-grader.sh ";
command += assignment;
system(command.c_str());
if (index < matches.size()) {
return strdup(matches[index++].c_str());
} else {
return nullptr;
}
}

bool parse_command_line(const std::string& line, std::string& command, std::string& assignment) const {
command.clear();
assignment.clear();
std::istringstream iss(line);
std::string arg;
while (iss >> arg) {
if (arg == "-h" || arg == "--help") {
print_help();
return false;
} else if (arg == "-m" || arg == "--multi-grader") {
command = arg;
if (iss >> arg) {
assignment = arg;
} else {
std::cerr << "myprogram: option requires an argument -- 'm'\n";
return false;
}
} else {
std::cerr << "myprogram: unrecognized option '" << arg << "'\n";
return false;
}
void print_help() const {
std::cout << "Usage: myprogram [options]\n";
std::cout << "\n";
std::cout << "Options:\n";
std::cout << " -h, --help Show this help message and exit\n";
std::cout << " -m, --multi-grader ASSIGNMENT\n";
std::cout << " Grade the specified assignment using "
"multi-grader\n";
}

void run_multi_grader(const std::string &assignment) const {
std::string command = "./multi-grader.sh ";
command += assignment;
system(command.c_str());
}

bool parse_command_line(const std::string &line, std::string &command,
std::string &assignment) const {
command.clear();
assignment.clear();
std::istringstream iss(line);
std::string arg;
while (iss >> arg) {
if (arg == "-h" || arg == "--help") {
print_help();
return false;
} else if (arg == "-m" || arg == "--multi-grader") {
command = arg;
if (iss >> arg) {
assignment = arg;
} else {
std::cerr << "myprogram: option requires an argument -- 'm'\n";
return false;
}
return true;
} else {
std::cerr << "myprogram: unrecognized option '" << arg << "'\n";
return false;
}
}
return true;
}
};

int main() {
CommandLineInterface cli;
cli.run();
return 0;
CommandLineInterface cli;
cli.run();
return 0;
}

0 comments on commit d97df98

Please sign in to comment.