132 lines
3.9 KiB
C++
132 lines
3.9 KiB
C++
#pragma once
|
||
|
||
#include "utils/utils.hpp"
|
||
#include <filesystem>
|
||
#include <vector>
|
||
#include <algorithm>
|
||
|
||
#include "logger/logger.hpp"
|
||
|
||
namespace rrr
|
||
{
|
||
// NONE - просто выводится текст. когда пупка пуста и нет контента вообще
|
||
// FILE - файл
|
||
// DIR - дирректория
|
||
enum class file_type
|
||
{
|
||
NONE, FILE, DIR
|
||
};
|
||
|
||
// класс-тип контента
|
||
// т.е. контентом является все, что может поместиться в терминал
|
||
// и это все называется файлом. ддиректория - это файл, файл - это файл и т.п.
|
||
// просто каждая сущность имеет свой тип см. выше
|
||
class file : public hack::utils::counter<int>
|
||
{
|
||
public:
|
||
file() = default;
|
||
file(std::filesystem::path, file_type, bool, bool);
|
||
file(file&&);
|
||
file(const file&);
|
||
|
||
public:
|
||
file& operator=(const file&);
|
||
bool operator<(const file&) const;
|
||
bool operator==(const file&) const;
|
||
friend std::ostream& operator<<(std::ostream&, const file&);
|
||
|
||
public:
|
||
int id;
|
||
std::filesystem::path path;
|
||
file_type type;
|
||
bool is_link = false;
|
||
bool is_hidden = false;
|
||
bool is_mark = false;
|
||
bool is_single_buffer = false;
|
||
};
|
||
}
|
||
|
||
namespace rrr::file_utils
|
||
{
|
||
using files = std::vector<file>;
|
||
|
||
inline bool is_hidden(const std::filesystem::path &p)
|
||
{
|
||
std::filesystem::path::string_type name = p.filename();
|
||
if(name != ".." && name != "." && name[0] == '.')
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
struct filesystem_convert
|
||
{
|
||
file operator()(const std::filesystem::directory_entry& entry) const
|
||
{
|
||
file_type type = file_type::FILE;
|
||
|
||
if (std::filesystem::is_directory(entry))
|
||
type = file_type::DIR;
|
||
|
||
auto is_link = std::filesystem::is_symlink(entry);
|
||
auto is_hidden = file_utils::is_hidden(entry);
|
||
|
||
return { entry.path(), type, is_link, is_hidden };
|
||
}
|
||
};
|
||
|
||
inline files get_files_struct(const std::filesystem::path& path)
|
||
{
|
||
files f;
|
||
|
||
try
|
||
{
|
||
std::filesystem::directory_iterator start(path);
|
||
std::filesystem::directory_iterator end;
|
||
std::transform(start, end, std::back_inserter(f), filesystem_convert());
|
||
}
|
||
catch(...)
|
||
{
|
||
f.push_back({ path / "no permission", file_type::NONE, false, false });
|
||
}
|
||
|
||
return f;
|
||
}
|
||
|
||
// не нужно тут передавать pwd, как ссылку
|
||
// т.к. один фиг копирование в content::fill произойдет из-за
|
||
// parent_path() метода, которым мы пользуемся при передачи сюда параметра
|
||
// НО пока эта информация уже устарела, т.к. много в коде изменилось
|
||
// по этому потом поэкспериментируй с запусками эстов конечно же
|
||
// т.е. передай по ссылке и посмотри на поведение
|
||
inline files fill(std::filesystem::path pwd)
|
||
{
|
||
files current_files = get_files_struct(pwd);
|
||
|
||
if (current_files.size() == 1 && current_files.at(0).path == pwd / "no permission")
|
||
{
|
||
return current_files;
|
||
}
|
||
|
||
files tmp;
|
||
tmp.reserve(current_files.size());
|
||
std::sort(current_files.begin(), current_files.end());
|
||
|
||
files tmp_files;
|
||
tmp_files.reserve(current_files.size());
|
||
|
||
std::copy_if(current_files.begin(), current_files.end(), std::back_inserter(tmp), [](const file& f) -> bool {
|
||
if (f.type == file_type::DIR) return true;
|
||
return false;
|
||
});
|
||
|
||
std::copy_if(current_files.begin(), current_files.end(), std::back_inserter(tmp_files), [](const file& f) -> bool {
|
||
if (f.type != file_type::DIR) return true;
|
||
return false;
|
||
});
|
||
|
||
tmp.insert(tmp.end(), tmp_files.begin(), tmp_files.end());
|
||
|
||
return tmp;
|
||
}
|
||
}
|