Skip to content

Commit

Permalink
Add "ls" and "cd" command
Browse files Browse the repository at this point in the history
  • Loading branch information
Serious-senpai committed Mar 10, 2024
1 parent dd15163 commit 7166161
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 25 deletions.
36 changes: 36 additions & 0 deletions src/commands/cd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <base.hpp>
#include <converter.hpp>
#include <error.hpp>
#include <standard.hpp>

class CdCommand : public BaseCommand
{
public:
using BaseCommand::run;

CdCommand() : BaseCommand("cd") {}

int run(const ParseResult &arguments) override
{
if (arguments.positional_arguments.size() == 1)
{
throw std::invalid_argument("No target directory specified");
}
else if (arguments.positional_arguments.size() > 2)
{
throw std::invalid_argument("Expected 1 argument only");
}
else
{
auto target = arguments.positional_arguments[1];
if (!SetCurrentDirectoryW(utf_convert(target).c_str()))
{
throw_last_error("Error when changing directory");
}
}

return 0;
}
};
59 changes: 59 additions & 0 deletions src/commands/ls.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <base.hpp>
#include <converter.hpp>
#include <error.hpp>
#include <standard.hpp>
#include <tables.hpp>
#include <units.hpp>
#include <utils.hpp>

class LsCommand : public BaseCommand
{
public:
using BaseCommand::run;

LsCommand() : BaseCommand("ls") {}

int run(const ParseResult &arguments) override
{
auto directory = get_working_directory();
if (arguments.positional_arguments.size() == 2)
{
directory = arguments.positional_arguments[1];
}
else if (arguments.positional_arguments.size() > 2)
{
throw std::invalid_argument("Expected at most 1 argument only");
}

Table displayer({"Name", "Type", "Size"});

directory += "\\*";
WIN32_FIND_DATAW data;
HANDLE h_file = FindFirstFileW(utf_convert(directory).c_str(), &data);
if (h_file == INVALID_HANDLE_VALUE)
{
throw_last_error("Error when listing directory");
}

do
{
long double size = ((long double)data.nFileSizeHigh * ((long double)MAXDWORD + 1.0L)) + (long double)data.nFileSizeLow;
bool is_directory = data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
displayer.add_row(
{utf_convert(std::wstring(data.cFileName)),
is_directory ? "DIR" : "FILE",
is_directory ? "-" : memory_size(size)});
} while (FindNextFileW(h_file, &data));

std::cout << displayer.display() << std::endl;

if (!FindClose(h_file))
{
throw_last_error("Error when closing file search handle");
}

return 0;
}
};
16 changes: 4 additions & 12 deletions src/commands/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <base.hpp>
#include <converter.hpp>
#include <error.hpp>
#include <standard.hpp>

class TypeCommand : public BaseCommand
Expand Down Expand Up @@ -32,25 +33,16 @@ class TypeCommand : public BaseCommand

if (h_file == INVALID_HANDLE_VALUE)
{
auto code = GetLastError();
throw std::runtime_error(format("Error opening file: %d", code));
throw_last_error("Error when opening file");
}

char buffer[BUFFER_SIZE] = {};
DWORD read = BUFFER_SIZE;
while (read == BUFFER_SIZE)
{
auto success = ReadFile(
h_file,
buffer,
BUFFER_SIZE,
&read,
NULL);

if (!success)
if (!ReadFile(h_file, buffer, BUFFER_SIZE, &read, NULL))
{
auto code = GetLastError();
throw std::runtime_error(format("Error reading file: %d", code));
throw_last_error("Error when reading file");
}

std::cout << std::string(buffer, buffer + read);
Expand Down
9 changes: 9 additions & 0 deletions src/include/error.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "format.hpp"
#include "standard.hpp"

void throw_last_error(const std::string &message)
{
throw std::runtime_error(format("%s: %d", message.c_str(), GetLastError()));
}
93 changes: 93 additions & 0 deletions src/include/tables.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#pragma once

#include "format.hpp"
#include "standard.hpp"

class Table
{
private:
std::vector<std::vector<std::string>> rows;

public:
const unsigned columns;
bool align_left = true;

Table(const std::initializer_list<std::string> &header) : columns(header.size())
{
rows.push_back(header);
}

void add_row(const std::initializer_list<std::string> &row)
{
if (row.size() != columns)
{
throw std::invalid_argument(format("Attempted to add a row of %d item(s) to a table with only %d column(s)", row.size(), columns));
}

rows.push_back(row);
}

std::string display()
{
std::vector<unsigned> column_widths(columns);
for (auto &row : rows)
{
for (unsigned column = 0; column < columns; column++)
{
column_widths[column] = std::max(column_widths[column], 2u + (unsigned)row[column].size());
}
}

std::vector<std::string> lines;
for (unsigned row = 0; row < rows.size(); row++)
{
std::string line;
for (unsigned column = 0; column < columns; column++)
{
if (align_left)
{
line += ' ';
line += rows[row][column];
}

for (unsigned i = 0; i < column_widths[column] - rows[row][column].size() - 1; i++)
{
line += ' ';
}

if (!align_left)
{
line += rows[row][column];
line += ' ';
}

line += '|';
}

lines.push_back(line);

if (row == 0)
{
std::string line;
for (unsigned column = 0; column < columns; column++)
{
for (unsigned i = 0; i < column_widths[column]; i++)
{
line += '-';
}
line += '+';
}
lines.push_back(line);
}
}

std::string result;
for (auto &line : lines)
{
result += line;
result += '\n';
}

return result;
}
};
34 changes: 34 additions & 0 deletions src/include/units.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "format.hpp"
#include "standard.hpp"

std::string memory_size(long double bytes)
{
std::string result = format("%.2LfB", bytes);
if (bytes > 1024)
{
bytes /= 1024;
result = format("%.2LfKB", bytes);

if (bytes > 1024)
{
bytes /= 1024;
result = format("%.2LfMB", bytes);

if (bytes > 1024)
{
bytes /= 1024;
result = format("%.2LfGB", bytes);

if (bytes > 1024)
{
bytes /= 1024;
result = format("%.2LfTB", bytes);
}
}
}
}

return result;
}
17 changes: 17 additions & 0 deletions src/include/utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "converter.hpp"
#include "standard.hpp"

std::string get_working_directory()
{
wchar_t buffer[MAX_PATH];
auto size = GetCurrentDirectoryW(MAX_PATH, buffer);

if (size == 0)
{
throw std::runtime_error("Error getting current directory.");
}

return utf_convert(std::wstring(buffer, buffer + size));
}
19 changes: 6 additions & 13 deletions src/shell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,18 @@
#include <split.hpp>
#include <standard.hpp>
#include <strip.hpp>
#include <utils.hpp>

#include "commands/args.hpp"
#include "commands/cd.hpp"
#include "commands/echo.hpp"
#include "commands/exit.hpp"
#include "commands/ls.hpp"
#include "commands/type.hpp"

// Windows uses UTF-16, but we process UTF-8 only
// https://utf8everywhere.org/

std::string get_working_directory()
{
wchar_t buffer[MAX_PATH];
auto size = GetCurrentDirectoryW(MAX_PATH, buffer);

if (size == 0)
{
throw std::runtime_error("Error getting current directory.");
}

return utf_convert(std::wstring(buffer, buffer + size));
}

const char title[] = R"(Windows lightweight command shell
Repository: https://github.com/Serious-senpai/lite-shell
Contribute: https://github.com/Serious-senpai/lite-shell/pulls
Expand All @@ -35,8 +25,10 @@ int main()
{
std::vector<CommandInvoker<BaseCommand>> commands;
commands.emplace_back(std::make_shared<ArgsCommand>());
commands.emplace_back(std::make_shared<CdCommand>());
commands.emplace_back(std::make_shared<EchoCommand>());
commands.emplace_back(std::make_shared<ExitCommand>());
commands.emplace_back(std::make_shared<LsCommand>());
commands.emplace_back(std::make_shared<TypeCommand>());

int errorlevel = 0;
Expand Down Expand Up @@ -95,6 +87,7 @@ int main()
}
ERROR_CODE(std::runtime_error, 900);
ERROR_CODE(std::invalid_argument, 901);
ERROR_CODE(std::bad_alloc, 902);

std::cerr << e.what() << std::endl;
}
Expand Down

0 comments on commit 7166161

Please sign in to comment.