Compare commits

...

10 Commits

Author SHA1 Message Date
e36e074d0a fix some info 2025-10-14 17:52:21 +03:00
chatlanin
a4c706d327 add run editor from rrr 2023-06-07 21:37:20 +03:00
chatlanin
1880278487 add enter key code as navigation right 2023-06-07 21:09:37 +03:00
chatlanin
57d96cab71 fix move to the end 2023-06-06 20:08:55 +03:00
chatlanin
73649a48e6 fix double help dialog 2023-05-10 22:13:55 +03:00
chatlanin
e5dca6cf34 fix path error 2023-05-10 22:01:52 +03:00
chatlanin
ea80038121 add simple preview code without colorize 2023-05-09 12:27:38 +03:00
chatlanin
740cb023a8 add fast navigation 2023-05-09 10:49:21 +03:00
chatlanin
b9cb5315dc fix readme 2023-04-27 09:21:17 +03:00
chatlanin
a7505b4073 add readme 2023-04-27 09:15:05 +03:00
44 changed files with 279 additions and 137 deletions

0
.gitignore vendored Normal file → Executable file
View File

39
README.md Normal file → Executable file
View File

@@ -0,0 +1,39 @@
Простой файловый менеджер, навеянный идеями ranger.
Автор никоим образом не претендует на чистоту реализации и верность исполнения.
Так что, если вы думаете, что можете сделать это по-другому, то, пожалуйста, сделайте это.
![video present](./rrr.gif)
На данном этапе проект запускается путем клонирования этого репозитория и сборки локально с использованием
установленной системы сборки meson.
**Шаги:**
1. установите мезон
2. клонируйте репозиторий
3. запустите: сборка установки мезона
4. запустите скрипт: . run
Особое внимание нужно обратить на зависимость try_engine. Это самописный движок на котором и написан данный менеджер.
В случае если окно запускается, а отображения информации нет - причина одна, в движке зашито слишком много шрифтов и
ваша видеокарта не очень это оценила.
Варианта два. Первое залезть в исходный код и переписать так, как вам кажется верным. Второе - поменять свою старую видеокарту на что-то
новее. В любом случае развлекайтесь, как вашей душе угодно.
Так же просмотрите файл meson.build лежащий в корне проекта, в нем указаны необходимые зависимости для работы. Их нужно установить в систему.
Цыфра v2 - означает, что это вторая реализация. Первая, была написана с использованием библиотеки ncurcess и находится где-то в аналах
данного сайта-хранилища. так что кому нравится это консольное дело смело начинайте с ним бдсмится.
Я, возможно, переодически буду дополнять данное чудо-творение разноообразными фишками, чистить свой не менее чудесный код от слишком заумных его вариаций, в общем
развивать и приводить это в более доступный и красивый вид. Но конкретных сроков и графиков данных работ не стоит и не будет стоять.
Чтобы эти слова не значили!
Ближайшие работы
- предпросмотр видео
- просмотр кода из файлов
- мультивыбор и действия над выбранными файлами
- читска кода и тестирование
PS: проект закрыт. Я открыл для себя yazi

0
bin/main.cpp Normal file → Executable file
View File

0
bin/meson.build Normal file → Executable file
View File

BIN
icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
img_logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

9
meson.build Normal file → Executable file
View File

@@ -1,7 +1,7 @@
project(
'rrr.v2',
'cpp',
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
version : '2.0.0',
default_options : [
'warning_level=1',
'optimization=3',
@@ -26,12 +26,7 @@ add_project_arguments (
#############################################################
#args = ['-lglfw', '-ldl', '-lGL', '-lpthread', '-lX11', '-lXxf86vm', '-lXrandr', '-lXi']
args = [
'-lopenal',
'-lsndfile',
'-lmpg123',
]
args = []
deps = [
dependency('TBB'),

View File

@@ -1,2 +0,0 @@
{"version": "1.0.0"}

BIN
rrr.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -11,3 +11,4 @@ if [[ -z "$1" ]]; then
else
meson test $1 -C build
fi

0
src/meson.build Normal file → Executable file
View File

1
src/rrr/buffer/buffer.hpp Normal file → Executable file
View File

@@ -45,4 +45,3 @@ namespace rrr
}
};
}

24
src/rrr/content/content.cpp Normal file → Executable file
View File

@@ -5,6 +5,7 @@
#include "logger/logger.hpp"
#include "buffer/buffer.hpp"
#include "utils/func.hpp"
namespace rrr
{
@@ -50,14 +51,14 @@ namespace rrr
set_history_cursor_position();
f = his.data.at(history_cursor_position);
}
catch(...) { hack::error()("Dont set history"); }
catch(...) {}
break;
case TYPE_WIN::NAVIGATION:
try
{
f = nav.data.at(navigation_cursor_position);
}
catch(...) { hack::error()("Dont set navigation"); }
catch(...) {}
break;
case TYPE_WIN::PREVIEW:
try
@@ -65,7 +66,7 @@ namespace rrr
set_preview_cursor_position();
f = prev.data.at(preview_cursor_position);
}
catch(...) { hack::error()("Dont set preview"); }
catch(...) {}
break;
}
@@ -187,16 +188,17 @@ namespace rrr
void content::create_file(std::string filename)
{
std::string cmd;
auto pwd = func::sheilding(PWD);
if (filename.find("/") != std::string::npos)
{
if (filename.at(filename.size() - 1) == '/') cmd = "mkdir -p " + std::string(PWD / filename);
else cmd = "mkdir -p " + std::string(PWD / std::filesystem::path(filename).parent_path())
+ " && touch " + std::string(PWD / filename);
if (filename.at(filename.size() - 1) == '/') cmd = "mkdir -p " + std::string(pwd / filename);
else cmd = "mkdir -p " + std::string(pwd / std::filesystem::path(filename).parent_path())
+ " && touch " + std::string(pwd / filename);
}
else
{
cmd = "touch " + std::string(PWD / filename);
cmd = "touch " + std::string(pwd / filename);
}
hack::utils::unix_cmd(cmd);
@@ -215,7 +217,7 @@ namespace rrr
new_name = old_name.parent_path() / std::filesystem::path(new_name);
}
hack::utils::unix_cmd("mv " + old_name.string() + " " + new_name.string());
hack::utils::unix_cmd("mv " + func::sheilding(old_name).string() + " " + func::sheilding(new_name).string());
nav.fill(PWD);
tbb::parallel_for(tbb::blocked_range<int>(0, nav.data.size()), [&](tbb::blocked_range<int> r)
@@ -245,7 +247,7 @@ namespace rrr
}
std::string cmd = std::filesystem::is_directory(f) ? "cp -R " : "cp ";
hack::utils::unix_cmd(cmd + f.string() + " " + target.string());
hack::utils::unix_cmd(cmd + func::sheilding(f).string() + " " + func::sheilding(target).string());
nav.fill(PWD);
check_cursor_position();
@@ -253,7 +255,7 @@ namespace rrr
void content::delete_file(file f)
{
std::string cmd = "delete " + f.path.string();
std::string cmd = "delete " + func::sheilding(f.path).string();
hack::utils::unix_cmd(cmd);
nav.fill(PWD);
increment_position(-1);
@@ -276,7 +278,7 @@ namespace rrr
}
std::string cmd = "mv ";
hack::utils::unix_cmd(cmd + f.string() + " " + target.string());
hack::utils::unix_cmd(cmd + func::sheilding(f).string() + " " + func::sheilding(target).string());
nav.fill(PWD);
tbb::parallel_for(tbb::blocked_range<int>(0, nav.data.size()), [&](tbb::blocked_range<int> r)

3
src/rrr/content/content.hpp Normal file → Executable file
View File

@@ -51,13 +51,12 @@ namespace rrr
int navigation_cursor_position = 0;
int preview_cursor_position = 0;
int history_cursor_position = 0;
file navigation_selected_file;
private:
void set_history_cursor_position();
void set_preview_cursor_position();
void check_cursor_position();
file navigation_selected_file;
};
}

0
src/rrr/content/file/file.cpp Normal file → Executable file
View File

0
src/rrr/content/file/file.hpp Normal file → Executable file
View File

0
src/rrr/content/history/history.cpp Normal file → Executable file
View File

0
src/rrr/content/history/history.hpp Normal file → Executable file
View File

0
src/rrr/content/navigation/navigation.cpp Normal file → Executable file
View File

0
src/rrr/content/navigation/navigation.hpp Normal file → Executable file
View File

0
src/rrr/content/preview/preview.cpp Normal file → Executable file
View File

0
src/rrr/content/preview/preview.hpp Normal file → Executable file
View File

2
src/rrr/layers/gui/browser/history/history.cpp Normal file → Executable file
View File

@@ -52,7 +52,7 @@ namespace rrr::layers::gui
TR_PUSH_FONT(SEMI_BOLD, 18);
ImGui::TextUnformatted(">");
ImGui::SameLine(22.f);
current_position = it - data->begin();
current_position = std::distance(data->begin(), it);
}
else
{

0
src/rrr/layers/gui/browser/history/history.hpp Normal file → Executable file
View File

79
src/rrr/layers/gui/browser/navigation/navigation.cpp Normal file → Executable file
View File

@@ -1,6 +1,7 @@
#include "navigation.hpp"
#include <algorithm>
#include <exception>
#include "try_engine/event/event_classificator.hpp"
#include "utils/types.hpp"
@@ -50,7 +51,7 @@ namespace rrr::layers::gui
push_style(item);
if (selected_file.path == item.path)
if (!selected_file.path.empty() && selected_file.path == item.path)
{
if (selected_file.is_hidden)
TR_PUSH_FONT(SEMI_BOLD_ITALIC, 18);
@@ -59,9 +60,8 @@ namespace rrr::layers::gui
ImGui::TextUnformatted(">");
ImGui::SameLine(22.f);
// HERE
// нужно использовать std::distance
current_position = it - data->begin();
current_position = std::distance(data->begin(), it);
}
else
{
@@ -200,28 +200,28 @@ namespace rrr::layers::gui
if (shift)
{
// удаление
if (shift && key.get_keycode() == try_engine::key::D)
if (key.get_keycode() == try_engine::key::D)
{
em->execute(types::event_type::SHOW_DELETE_ONE_FILE_DIALOG, selected_file);
freeze = true;
}
// создание файла/директории
if (shift && key.get_keycode() == try_engine::key::A)
if (key.get_keycode() == try_engine::key::A)
{
em->execute(types::event_type::SHOW_CREATE_FILE_DIALOG, nullptr);
freeze = true;
}
// переименование файла/директории
if (shift && key.get_keycode() == try_engine::key::R)
if (key.get_keycode() == try_engine::key::R)
{
em->execute(types::event_type::SHOW_RENAME_FILE_DIALOG, selected_file);
freeze = true;
}
// перемещение в конец списка
if (shift && key.get_keycode() == try_engine::key::G)
if (key.get_keycode() == try_engine::key::G)
{
cnt->increment_position(data->size());
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
@@ -231,15 +231,34 @@ namespace rrr::layers::gui
}
// вставка из single_buffer
if (shift && key.get_keycode() == try_engine::key::P)
if (key.get_keycode() == try_engine::key::P)
{
paste_from_copy();
paste_from_cut();
}
return;
// перемещение на несколько позиций вниз
if (key.get_keycode() == try_engine::key::J)
{
cnt->increment_position((data->size() - current_position) / 4);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_DOWN, nullptr);
set_delta(MOVE_DIRECTION::DOWN);
set_scroll();
}
// перемещение на несколько позиций вверх
if (key.get_keycode() == try_engine::key::K)
{
cnt->increment_position(current_position - current_position / 4);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_UP, nullptr);
set_delta(MOVE_DIRECTION::UP);
set_scroll();
}
}
else
{
if (key.get_keycode() == try_engine::key::J)
{
cnt->increment_position(STEP_DOWN);
@@ -265,8 +284,25 @@ namespace rrr::layers::gui
set_scroll();
}
if (key.get_keycode() == try_engine::key::ENTER)
{
if (std::filesystem::is_directory(selected_file.path))
{
cnt->navigation_right();
data = cnt->get(TYPE_WIN::NAVIGATION);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
em->execute(types::event_type::NAVIGATION_RIGHT, nullptr);
set_scroll();
}
else
{
run_app();
}
}
if (key.get_keycode() == try_engine::key::L)
{
if (!std::filesystem::is_directory(selected_file.path)) return;
cnt->navigation_right();
data = cnt->get(TYPE_WIN::NAVIGATION);
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
@@ -333,8 +369,9 @@ namespace rrr::layers::gui
em->execute(types::event_type::SHOW_HELP_DIALOG, nullptr);
freeze = true;
}
}
detect_img();
detect_file();
}
void navigation::released(system_event& e)
@@ -396,6 +433,8 @@ namespace rrr::layers::gui
void navigation::set_scroll()
{
if (selected_file.path.empty()) return;
delta = 0;
current_position = 0;
cursor_position = 0;
@@ -436,11 +475,27 @@ namespace rrr::layers::gui
selected_file = cnt->get_selected_file(TYPE_WIN::NAVIGATION);
}
void navigation::detect_img()
void navigation::detect_file()
{
if (selected_file.path.empty()) return;
if (std::filesystem::is_directory(selected_file.path)) return;
if (selected_file.path.extension() == ".jpg" ||
selected_file.path.extension() == ".jpeg" ||
selected_file.path.extension() == ".png")
em->execute(types::event_type::SHOW_IMG, selected_file.path);
else
em->execute(types::event_type::SHOW_SRC, selected_file.path);
}
void navigation::run_app()
{
// if (selected_file.path.extension() == ".mp3" ||
// selected_file.path.extension() == ".mp4" ||
// selected_file.path.extension() == ".wave")
// HERE начинаем тут
// сделать запуск разных программ из под rrr
system(("kitty --name \"project_rrr_editor\" --directory " + selected_file.path.parent_path().string() + " nv ").c_str());
}
}

4
src/rrr/layers/gui/browser/navigation/navigation.hpp Normal file → Executable file
View File

@@ -68,9 +68,11 @@ namespace rrr::layers::gui
std::string get_file_content(file&);
void set_delta(MOVE_DIRECTION);
void set_scroll();
void run_app();
void paste_from_copy(); // вставка после копирования
void paste_from_cut(); // вставки после вырезания
void detect_img();
void detect_file(); // определяем не кортинка ли это или определяем не является ли
// это что-то типа кода, который можно вывести на просмотр
};
}

30
src/rrr/layers/gui/browser/preview/preview.cpp Normal file → Executable file
View File

@@ -43,16 +43,22 @@ namespace rrr::layers::gui
{
make_media = false;
tx.make();
frame = cv::imread(media_path);
frame = cv::imread(src_path);
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGBA);
tx.bind(frame);
media_show = true;
hack::log()(width, height);
}
if (media_show)
tx.draw(ImVec2(pos.x + 830.f, pos.y), ImVec2(width + 850.f, frame.rows / 1.6f));
if (src_show)
{
TR_PUSH_FONT(MEDIUM, 18);
ImGui::TextUnformatted(src_data.data());
TR_POP_FONT();
}
for (files::iterator it = begin; it != end; ++it)
{
auto item = *it;
@@ -68,7 +74,7 @@ namespace rrr::layers::gui
TR_PUSH_FONT(SEMI_BOLD, 18);
ImGui::TextUnformatted(">");
ImGui::SameLine(22.f);
current_position = it - data->begin();
current_position = std::distance(data->begin(), it);
}
else
{
@@ -114,7 +120,9 @@ namespace rrr::layers::gui
case types::event_type::NAVIGATION_DOWN:
case types::event_type::NAVIGATION_LEFT:
case types::event_type::NAVIGATION_RIGHT:
media_path.clear();
src_path.clear();
src_data.clear();
src_show = false;
media_show = false;
selected_file = cnt->get_selected_file(TYPE_WIN::PREVIEW);
cursor_position = 0;
@@ -123,9 +131,21 @@ namespace rrr::layers::gui
set_scroll();
break;
case types::event_type::SHOW_IMG:
media_path = std::any_cast<std::filesystem::path>(value);
src_path = std::any_cast<std::filesystem::path>(value);
make_media = true;
break;
case types::event_type::SHOW_SRC:
src_path = std::any_cast<std::filesystem::path>(value);
// HERE
// пока не подсвечиваем, для этого нужно видимо написать свой токенайзер
// и разбирать всю баш строку на наличие цветов
// буз этого пока поживешь, не сломаешься!
// src_data = hack::utils::unix_cmd("bat --style=plain --color=always " + src_path.string());
if (std::filesystem::is_empty(src_path)) src_data = "no data";
else
src_data = hack::utils::unix_cmd("cat " + src_path.string());
src_show = true;
break;
default:
break;
}

4
src/rrr/layers/gui/browser/preview/preview.hpp Normal file → Executable file
View File

@@ -42,12 +42,14 @@ namespace rrr::layers::gui
int delta = 0;
enum class MOVE_DIRECTION { UP, DOWN };
std::filesystem::path media_path;
try_engine::texture tx;
cv::Mat frame;
cv::VideoCapture cap;
std::filesystem::path src_path;
bool media_show = false;
bool make_media = false;
bool src_show = false;
std::string src_data; // данные для показа кода из файла
private:
const ImVec4 dir_color = func::get_IMGUI_color<ImVec4>(91.f, 128.f, 191.f);

13
src/rrr/layers/gui/dialogs/dialogs.cpp Normal file → Executable file
View File

@@ -142,9 +142,6 @@ namespace rrr::layers::gui
if (rename_dialog)
rename();
}
if (help_dialog && key.get_keycode() == try_engine::key::F1)
cancel();
}
void dialogs::released(system_event& e)
@@ -284,7 +281,8 @@ namespace rrr::layers::gui
void dialogs::draw_help_dialog()
{
height = try_engine::application::get()->get_window()->height() / 2.7f;
hack::log()("draw_help_dialog");
height = try_engine::application::get()->get_window()->height() / 2.4f;
TR_PUSH_FONT(MEDIUM, 16);
@@ -300,18 +298,21 @@ namespace rrr::layers::gui
ImGui::TextUnformatted(label.data());
ImGui::Separator();
ImGui::TextUnformatted("Копирование: С / backspace");
ImGui::TextUnformatted("Копирование: c / backspace");
ImGui::TextUnformatted("Вставка: P");
ImGui::TextUnformatted("Удаление: D");
ImGui::TextUnformatted("Переименование: R");
ImGui::TextUnformatted("Создание: A");
ImGui::TextUnformatted("Вырезание: x");
ImGui::Separator();
ImGui::TextUnformatted("Перемещение в начало: gg");
ImGui::TextUnformatted("Перемещение в конец: G");
ImGui::TextUnformatted("Быстрое перемещение вверх: J");
ImGui::TextUnformatted("Быстрое перемещение вниз: K");
ImGui::Separator();
ImGui::TextUnformatted("Выход из помощи: F1");
ImGui::TextUnformatted("Выход из диалогов: ESCAPE");
TR_POP_FONT();
}

0
src/rrr/layers/gui/dialogs/dialogs.hpp Normal file → Executable file
View File

0
src/rrr/meson.build Normal file → Executable file
View File

12
src/rrr/rrr.hpp Normal file → Executable file
View File

@@ -1,3 +1,4 @@
#include "logger/logger.hpp"
#include "try_engine/try_engine.hpp"
#include "content/content.hpp"
@@ -16,9 +17,14 @@ namespace rrr
public:
rrr_impl(std::string app_name) : try_engine::application{ app_name }
{
// HERE
// убрать это в релизе
cnt.set_pwd("/mnt/develop/projects/cpp/rrr/dir_for_tests");
std::string pwd = hack::utils::unix_cmd("pwd");
// перемещаем все знаки перевода строки в конец строки
// т.к. там это есть и это вызывает ошибку
auto it = std::remove(pwd.begin(), pwd.end(), '\n');
pwd.erase(it, pwd.end());
cnt.set_pwd(std::filesystem::path(pwd));
cnt.fill();
};
~rrr_impl() = default;

22
src/rrr/utils/func.hpp Normal file → Executable file
View File

@@ -1,5 +1,7 @@
#pragma once
#include <filesystem>
namespace rrr::func
{
template<typename Color>
@@ -7,4 +9,24 @@ namespace rrr::func
{
return Color(r / 255.f, g / 255.f, b / 255.f, 1.f);
}
// для экоранирования путей чтоб unix команды нормально выполнялись
// правила тут вилимо будут добавлятся так что эт не конец:(
inline std::filesystem::path sheilding(std::filesystem::path PWD)
{
std::string pwd_local;
for (char c : PWD.string()) {
if (c == ' ')
pwd_local += "\\ ";
else if (c == '(')
pwd_local += "\\(";
else if (c == ')')
pwd_local += "\\)";
else
pwd_local += c;
}
return pwd_local;
}
}

3
src/rrr/utils/types.hpp Normal file → Executable file
View File

@@ -18,7 +18,8 @@ namespace rrr::types
SHOW_RENAME_FILE_DIALOG,
RENAME_FILE,
SHOW_HELP_DIALOG,
SHOW_IMG
SHOW_IMG,
SHOW_SRC // показываем содержимое файла если это код
};
}

0
subprojects/glad.wrap Normal file → Executable file
View File

0
subprojects/glfw.wrap Normal file → Executable file
View File

0
subprojects/glm.wrap Normal file → Executable file
View File

0
subprojects/gtest.wrap Normal file → Executable file
View File

0
subprojects/hack.wrap Normal file → Executable file
View File

0
subprojects/imgui.wrap Normal file → Executable file
View File

0
subprojects/nlohmann_json.wrap Normal file → Executable file
View File

0
subprojects/taglib.wrap Normal file → Executable file
View File

0
subprojects/try_engine.wrap Normal file → Executable file
View File

0
tests/meson.build Normal file → Executable file
View File