From 0c5bfaf4d067e5877e16e8f4d2faf4022e122dd2 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 11:16:01 +0300 Subject: [PATCH 01/24] component: UI Basic ls in ncurses window - Require C++17 because of std::filesystem usage - Draw sorted listing of cwd in main window Signed-off-by: Pavel Kalugin --- CMakeLists.txt | 2 ++ include/rang.h | 4 ++++ src/rang.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8804a4f..bf7e3e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ project(rang) set(CURSES_NEED_NCURSES TRUE) find_package(Curses REQUIRED) +set(CMAKE_CXX_STANDARD 17) + add_subdirectory(src) target_include_directories(rang PUBLIC include) diff --git a/include/rang.h b/include/rang.h index 8467d8b..b286505 100644 --- a/include/rang.h +++ b/include/rang.h @@ -1,5 +1,9 @@ +#include +#include #include +namespace fs = std::filesystem; + namespace rang { const std::string MESSAGE = "Hello, world\n"; diff --git a/src/rang.cpp b/src/rang.cpp index 07f8bb5..5da902c 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,12 +1,50 @@ #include "rang.h" +#include +#include +#include #include +#include +#include int main(int argc, char *argv[]) { - initscr(); /* Start curses mode */ - printw(rang::MESSAGE.c_str()); /* Print Hello World */ - refresh(); /* Print it on to the real screen */ - getch(); /* Wait for user input */ - endwin(); /* End curses mode */ + WINDOW *my_win; + int width, height; + int ch; + + initscr(); /* Start curses mode */ + cbreak(); /* Line buffering disabled, Pass on + * everty thing to me */ + keypad(stdscr, TRUE); /* I need that nifty F1 */ + noecho(); + + height = LINES; + width = COLS; + refresh(); + WINDOW *box_win = newwin(height, width, 0, 0); + box(box_win, 0, 0); + my_win = newwin(height - 2, width - 2, 1, 1); + wrefresh(box_win); + wrefresh(my_win); + std::vector filtered; + auto it = fs::directory_iterator("."); + std::copy_if(fs::begin(it), fs::end(it), std::back_insert_iterator(filtered), + [](fs::directory_entry entry) -> bool { + return entry.path().filename().string().front() != '.'; + }); + std::sort(filtered.begin(), filtered.end(), + [](fs::directory_entry entry1, fs::directory_entry entry2) -> bool { + if (entry1.is_directory() != entry2.is_directory()) { + return entry1.is_directory(); + } + return entry1.path().filename().string() < entry2.path().filename().string(); + }); + for (auto entry : filtered) { + wprintw(my_win, "%s\n", entry.path().filename().c_str()); + } + wrefresh(my_win); + getch(); + + endwin(); /* End curses mode */ return 0; } From feab7cdb127ccfc0e64b261d7d52d14f970dfb58 Mon Sep 17 00:00:00 2001 From: pavel-the-best Date: Mon, 7 Dec 2020 08:21:24 +0000 Subject: [PATCH 02/24] Apply formatting changes --- src/rang.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rang.cpp b/src/rang.cpp index 5da902c..2538e7b 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -37,7 +37,8 @@ int main(int argc, char *argv[]) if (entry1.is_directory() != entry2.is_directory()) { return entry1.is_directory(); } - return entry1.path().filename().string() < entry2.path().filename().string(); + return entry1.path().filename().string() < + entry2.path().filename().string(); }); for (auto entry : filtered) { wprintw(my_win, "%s\n", entry.path().filename().c_str()); From 27167fc8b9cf48f259d7e64af68caccd14996200 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 11:23:31 +0300 Subject: [PATCH 03/24] fixup #1 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf7e3e0..7776d29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CURSES_NEED_NCURSES TRUE) find_package(Curses REQUIRED) set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) add_subdirectory(src) From b4a7b03323b3cbf53aa6bee0cfd16bab8b7ad6b6 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 11:29:39 +0300 Subject: [PATCH 04/24] fixup #2 --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 12bd8e1..ca266d1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ add_executable (rang rang.cpp) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) -target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES}) +target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} stdc++fs) From 13fbf3e91ac341a5d254799de0837e62dd4e00c1 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 11:39:31 +0300 Subject: [PATCH 05/24] fixup #3 --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0412588..3606ca1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,6 +11,7 @@ jobs: # cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix runs-on: ubuntu-latest + container: rikorose/gcc-cmake:latest steps: - uses: actions/checkout@v2 From 821a8bd8809e1cb707259e1bd9d89f2bae5cd97f Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 12:38:25 +0300 Subject: [PATCH 06/24] fixup #7 --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3606ca1..243481d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,26 +19,26 @@ jobs: - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{runner.workspace}}/build + run: cmake -E make_directory $GITHUB_WORKSPACE/build - name: Configure CMake # Use a bash shell so we can use the same syntax for environment variable # access regardless of the host operating system shell: bash - working-directory: ${{runner.workspace}}/build + working-directory: $GITHUB_WORKSPACE/build # Note the current convention is to use the -S and -B options here to specify source # and build directories, but this is only available with CMake 3.13 and higher. # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build - working-directory: ${{runner.workspace}}/build + working-directory: $GITHUB_WORKSPACE/build shell: bash # Execute the build. You can specify a specific target with "--target " run: cmake --build . --config $BUILD_TYPE - name: Test - working-directory: ${{runner.workspace}}/build + working-directory: $GITHUB_WORKSPACE/build shell: bash # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail From d91556ca3feca7cb420ebea7080f32784486b870 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 12:43:19 +0300 Subject: [PATCH 07/24] fixup #8 --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 243481d..473739d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,7 +29,7 @@ jobs: # Note the current convention is to use the -S and -B options here to specify source # and build directories, but this is only available with CMake 3.13 and higher. # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build working-directory: $GITHUB_WORKSPACE/build From ce45cbae407760dfaa399ef3f872a6f7dbd451d3 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 12:46:30 +0300 Subject: [PATCH 08/24] fixup #9 --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 473739d..f653f75 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,26 +19,26 @@ jobs: - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory $GITHUB_WORKSPACE/build + run: cmake -E make_directory build - name: Configure CMake # Use a bash shell so we can use the same syntax for environment variable # access regardless of the host operating system shell: bash - working-directory: $GITHUB_WORKSPACE/build + working-directory: build # Note the current convention is to use the -S and -B options here to specify source # and build directories, but this is only available with CMake 3.13 and higher. # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE - name: Build - working-directory: $GITHUB_WORKSPACE/build + working-directory: build shell: bash # Execute the build. You can specify a specific target with "--target " run: cmake --build . --config $BUILD_TYPE - name: Test - working-directory: $GITHUB_WORKSPACE/build + working-directory: build shell: bash # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail From 524826a293002cbc00505f9465b5124f7481b1af Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 7 Dec 2020 14:32:38 +0300 Subject: [PATCH 09/24] work --- include/buffer.hpp | 37 ++++++++++++++++++++++++++++++++++++ include/{rang.h => rang.hpp} | 8 ++++---- src/CMakeLists.txt | 2 +- src/buffer.cpp | 28 +++++++++++++++++++++++++++ src/rang.cpp | 23 ++++++---------------- 5 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 include/buffer.hpp rename include/{rang.h => rang.hpp} (53%) create mode 100644 src/buffer.cpp diff --git a/include/buffer.hpp b/include/buffer.hpp new file mode 100644 index 0000000..499c05f --- /dev/null +++ b/include/buffer.hpp @@ -0,0 +1,37 @@ +#ifndef __BUFFER_HPP +#define __BUFFER_HPP + +#include "rang.hpp" +#include +#include +#include + +namespace fs = std::filesystem; + +class Buffer +{ + public: + std::vector contents; + + Buffer() = default; + + void update(); +}; + +class Dummy : Buffer +{ +}; + +class DirectoryListing : public Buffer +{ + private: + fs::directory_iterator it; + + public: + fs::path directory; + + DirectoryListing(fs::path _directory); + + void update(); +}; +#endif diff --git a/include/rang.h b/include/rang.hpp similarity index 53% rename from include/rang.h rename to include/rang.hpp index b286505..9ba244c 100644 --- a/include/rang.h +++ b/include/rang.hpp @@ -1,10 +1,10 @@ -#include -#include -#include +#ifndef __RANG_HPP +#define __RANG_HPP -namespace fs = std::filesystem; +#include namespace rang { const std::string MESSAGE = "Hello, world\n"; } +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca266d1..0d6fec2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -add_executable (rang rang.cpp) +add_executable (rang rang.cpp buffer.cpp) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} stdc++fs) diff --git a/src/buffer.cpp b/src/buffer.cpp new file mode 100644 index 0000000..e3894a1 --- /dev/null +++ b/src/buffer.cpp @@ -0,0 +1,28 @@ +#include "buffer.hpp" +#include +#include + +DirectoryListing::DirectoryListing(fs::path _directory) : directory(_directory) +{ + it = fs::directory_iterator(directory); +}; + +void DirectoryListing::update() +{ + std::vector filtered; + std::copy_if(fs::begin(it), fs::end(it), std::back_insert_iterator(filtered), + [](fs::directory_entry entry) -> bool { + return entry.path().filename().string().front() != '.'; + }); + std::sort(filtered.begin(), filtered.end(), + [](fs::directory_entry entry1, fs::directory_entry entry2) -> bool { + if (entry1.is_directory() != entry2.is_directory()) { + return entry1.is_directory(); + } + return entry1.path().filename().string() < entry2.path().filename().string(); + }); + contents.resize(filtered.size()); + transform( + filtered.begin(), filtered.end(), contents.begin(), + [](fs::directory_entry entry) -> std::string { return entry.path().filename().string(); }); +} diff --git a/src/rang.cpp b/src/rang.cpp index 2538e7b..9f40059 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,4 +1,5 @@ -#include "rang.h" +#include "rang.hpp" +#include "buffer.hpp" #include #include #include @@ -26,22 +27,10 @@ int main(int argc, char *argv[]) my_win = newwin(height - 2, width - 2, 1, 1); wrefresh(box_win); wrefresh(my_win); - std::vector filtered; - auto it = fs::directory_iterator("."); - std::copy_if(fs::begin(it), fs::end(it), std::back_insert_iterator(filtered), - [](fs::directory_entry entry) -> bool { - return entry.path().filename().string().front() != '.'; - }); - std::sort(filtered.begin(), filtered.end(), - [](fs::directory_entry entry1, fs::directory_entry entry2) -> bool { - if (entry1.is_directory() != entry2.is_directory()) { - return entry1.is_directory(); - } - return entry1.path().filename().string() < - entry2.path().filename().string(); - }); - for (auto entry : filtered) { - wprintw(my_win, "%s\n", entry.path().filename().c_str()); + DirectoryListing lst("."); + lst.update(); + for (std::string &dirname : lst.contents) { + wprintw(my_win, "%s\n", dirname.c_str()); } wrefresh(my_win); getch(); From 2cde7b1a4dcf2ef31e9694f63e4fbb46e3bf1646 Mon Sep 17 00:00:00 2001 From: pavel-the-best Date: Mon, 7 Dec 2020 11:33:56 +0000 Subject: [PATCH 10/24] Apply formatting changes --- src/buffer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/buffer.cpp b/src/buffer.cpp index e3894a1..5b5eaea 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -19,10 +19,12 @@ void DirectoryListing::update() if (entry1.is_directory() != entry2.is_directory()) { return entry1.is_directory(); } - return entry1.path().filename().string() < entry2.path().filename().string(); + return entry1.path().filename().string() < + entry2.path().filename().string(); }); contents.resize(filtered.size()); - transform( - filtered.begin(), filtered.end(), contents.begin(), - [](fs::directory_entry entry) -> std::string { return entry.path().filename().string(); }); + transform(filtered.begin(), filtered.end(), contents.begin(), + [](fs::directory_entry entry) -> std::string { + return entry.path().filename().string(); + }); } From ab403cbebfb415bdc8e80bda1a5c377e819d2e28 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Wed, 9 Dec 2020 18:45:50 +0300 Subject: [PATCH 11/24] even more work --- include/buffer.hpp | 10 ++++----- src/CMakeLists.txt | 4 +++- src/buffer.cpp | 4 ++-- src/console_io/CMakeLists.txt | 6 ++++++ src/console_io/include/window.hpp | 29 +++++++++++++++++++++++++ src/console_io/src/window.cpp | 35 +++++++++++++++++++++++++++++++ src/rang.cpp | 24 ++++++++++----------- 7 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 src/console_io/CMakeLists.txt create mode 100644 src/console_io/include/window.hpp create mode 100644 src/console_io/src/window.cpp diff --git a/include/buffer.hpp b/include/buffer.hpp index 499c05f..1c962db 100644 --- a/include/buffer.hpp +++ b/include/buffer.hpp @@ -8,21 +8,21 @@ namespace fs = std::filesystem; -class Buffer +class buffer { public: std::vector contents; - Buffer() = default; + buffer() = default; void update(); }; -class Dummy : Buffer +class dummy : buffer { }; -class DirectoryListing : public Buffer +class directory_listing : public buffer { private: fs::directory_iterator it; @@ -30,7 +30,7 @@ class DirectoryListing : public Buffer public: fs::path directory; - DirectoryListing(fs::path _directory); + directory_listing(fs::path _directory); void update(); }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d6fec2..05d4cdd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,6 @@ +add_subdirectory(console_io) + add_executable (rang rang.cpp buffer.cpp) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) -target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} stdc++fs) +target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} console_io) diff --git a/src/buffer.cpp b/src/buffer.cpp index 5b5eaea..523cb2d 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -2,12 +2,12 @@ #include #include -DirectoryListing::DirectoryListing(fs::path _directory) : directory(_directory) +directory_listing::directory_listing(fs::path _directory) : directory(_directory) { it = fs::directory_iterator(directory); }; -void DirectoryListing::update() +void directory_listing::update() { std::vector filtered; std::copy_if(fs::begin(it), fs::end(it), std::back_insert_iterator(filtered), diff --git a/src/console_io/CMakeLists.txt b/src/console_io/CMakeLists.txt new file mode 100644 index 0000000..1d72051 --- /dev/null +++ b/src/console_io/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.17) +project(console_io) + +add_library(console_io OBJECT src/window.cpp) + +target_include_directories(console_io PUBLIC include) diff --git a/src/console_io/include/window.hpp b/src/console_io/include/window.hpp new file mode 100644 index 0000000..70caabf --- /dev/null +++ b/src/console_io/include/window.hpp @@ -0,0 +1,29 @@ +#ifndef __WINDOW_HPP +#define __WINDOW_HPP + +#include +#include + +class window +{ + private: + WINDOW *win_ptr; + + public: + int size_x; + int size_y; + + window(int _size_x, int _size_y, int offset_x, int offset_y); + + ~window(); + + void refresh(); + + void move(int x, int y); + + void output(std::string s); + + void move_and_output(int x, int y, std::string s); +}; + +#endif diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp new file mode 100644 index 0000000..2c8a48f --- /dev/null +++ b/src/console_io/src/window.cpp @@ -0,0 +1,35 @@ +#include "window.hpp" +#include + +window::window(int _size_x, int _size_y, int offset_x, int offset_y) + : size_x(_size_x), size_y(_size_y) +{ + win_ptr = newwin(size_y, size_x, offset_y, offset_x); + refresh(); +} + +window::~window() +{ + refresh(); + delwin(win_ptr); +} + +void window::refresh() +{ + wrefresh(win_ptr); +} + +void window::move(int x, int y) +{ + wmove(win_ptr, y, x); +} + +void window::output(std::string s) +{ + waddstr(win_ptr, s.c_str()); +} + +void window::move_and_output(int x, int y, std::string s) +{ + mvwaddstr(win_ptr, y, x, s.c_str()); +} diff --git a/src/rang.cpp b/src/rang.cpp index 9f40059..23bb2b6 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,5 +1,6 @@ #include "rang.hpp" #include "buffer.hpp" +#include "window.hpp" #include #include #include @@ -9,11 +10,12 @@ int main(int argc, char *argv[]) { - WINDOW *my_win; int width, height; int ch; - initscr(); /* Start curses mode */ + initscr(); /* Start curses mode */ + start_color(); + use_default_colors(); cbreak(); /* Line buffering disabled, Pass on * everty thing to me */ keypad(stdscr, TRUE); /* I need that nifty F1 */ @@ -22,19 +24,15 @@ int main(int argc, char *argv[]) height = LINES; width = COLS; refresh(); - WINDOW *box_win = newwin(height, width, 0, 0); - box(box_win, 0, 0); - my_win = newwin(height - 2, width - 2, 1, 1); - wrefresh(box_win); - wrefresh(my_win); - DirectoryListing lst("."); + window mywin(width - 2, height - 2, 1, 1); + directory_listing lst("."); lst.update(); - for (std::string &dirname : lst.contents) { - wprintw(my_win, "%s\n", dirname.c_str()); + int current = 0; + for (std::string &line : lst.contents) { + mywin.move_and_output(0, current++, line); } - wrefresh(my_win); + mywin.refresh(); getch(); - - endwin(); /* End curses mode */ + endwin(); return 0; } From 3a243deea526bf8912536a7c03731d13de8b17bf Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Wed, 9 Dec 2020 21:57:50 +0300 Subject: [PATCH 12/24] move everything to namespaces. control destruction order --- src/console_io/CMakeLists.txt | 2 +- src/console_io/include/base.hpp | 18 ++++++++++++++++ src/console_io/include/console_io.hpp | 5 +++++ src/console_io/include/window.hpp | 23 +++++++++++++++----- src/console_io/src/base.cpp | 22 +++++++++++++++++++ src/console_io/src/window.cpp | 31 +++++++++++++++++++++++---- src/rang.cpp | 17 ++++++--------- 7 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 src/console_io/include/base.hpp create mode 100644 src/console_io/include/console_io.hpp create mode 100644 src/console_io/src/base.cpp diff --git a/src/console_io/CMakeLists.txt b/src/console_io/CMakeLists.txt index 1d72051..7a2accd 100644 --- a/src/console_io/CMakeLists.txt +++ b/src/console_io/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.17) project(console_io) -add_library(console_io OBJECT src/window.cpp) +add_library(console_io OBJECT src/window.cpp src/base.cpp) target_include_directories(console_io PUBLIC include) diff --git a/src/console_io/include/base.hpp b/src/console_io/include/base.hpp new file mode 100644 index 0000000..5355278 --- /dev/null +++ b/src/console_io/include/base.hpp @@ -0,0 +1,18 @@ +#ifndef __SCREEN_HPP +#define __SCREEN_HPP + +#include "window.hpp" +#include + +namespace console_io +{ +class ncurses : public window +{ + public: + ncurses(); + + ~ncurses(); +}; +} // namespace console_io + +#endif diff --git a/src/console_io/include/console_io.hpp b/src/console_io/include/console_io.hpp new file mode 100644 index 0000000..ba78c30 --- /dev/null +++ b/src/console_io/include/console_io.hpp @@ -0,0 +1,5 @@ +#ifndef __CONSOLE_IO_HPP +#define __CONSOLE_IO_HPP +#include "base.hpp" +#include "window.hpp" +#endif diff --git a/src/console_io/include/window.hpp b/src/console_io/include/window.hpp index 70caabf..9ff1860 100644 --- a/src/console_io/include/window.hpp +++ b/src/console_io/include/window.hpp @@ -1,22 +1,32 @@ #ifndef __WINDOW_HPP #define __WINDOW_HPP +#include #include #include +#include +namespace console_io +{ class window { - private: - WINDOW *win_ptr; + protected: + WINDOW *win_ptr = nullptr; public: - int size_x; - int size_y; + int size_x = 0; + int size_y = 0; + window *parent = nullptr; + std::vector subwindows; + + window() = default; - window(int _size_x, int _size_y, int offset_x, int offset_y); + window(int _size_x, int _size_y, int offset_x, int offset_y, window *_parent = nullptr); ~window(); + bool operator==(const window &other); + void refresh(); void move(int x, int y); @@ -24,6 +34,9 @@ class window void output(std::string s); void move_and_output(int x, int y, std::string s); + + window subwindow(int _size_x, int _size_y, int offset_x, int offset_y); }; +} // namespace console_io #endif diff --git a/src/console_io/src/base.cpp b/src/console_io/src/base.cpp new file mode 100644 index 0000000..2d4fc15 --- /dev/null +++ b/src/console_io/src/base.cpp @@ -0,0 +1,22 @@ +#include "base.hpp" +#include + +using namespace console_io; + +ncurses::ncurses() +{ + win_ptr = initscr(); +} + +ncurses::~ncurses() +{ + if (win_ptr == stdscr) { // guarantee Liskov substitution + endwin(); + } else { + if (parent != nullptr) { + parent->subwindows.erase( + std::find(parent->subwindows.begin(), parent->subwindows.end(), *this)); + } + delwin(win_ptr); + } +} diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp index 2c8a48f..4c40345 100644 --- a/src/console_io/src/window.cpp +++ b/src/console_io/src/window.cpp @@ -1,8 +1,10 @@ #include "window.hpp" -#include +#include -window::window(int _size_x, int _size_y, int offset_x, int offset_y) - : size_x(_size_x), size_y(_size_y) +using namespace console_io; + +window::window(int _size_x, int _size_y, int offset_x, int offset_y, window *_parent) + : size_x(_size_x), size_y(_size_y), parent(_parent) { win_ptr = newwin(size_y, size_x, offset_y, offset_x); refresh(); @@ -10,10 +12,21 @@ window::window(int _size_x, int _size_y, int offset_x, int offset_y) window::~window() { - refresh(); + if (parent != nullptr) { + // this window must be deleted from parent's subwindows in order to avoid double + // destruction + parent->subwindows.erase( + std::find(parent->subwindows.begin(), parent->subwindows.end(), *this)); + } + subwindows.clear(); delwin(win_ptr); } +bool window::operator==(const window &other) +{ + return win_ptr == other.win_ptr; +} + void window::refresh() { wrefresh(win_ptr); @@ -33,3 +46,13 @@ void window::move_and_output(int x, int y, std::string s) { mvwaddstr(win_ptr, y, x, s.c_str()); } + +window window::subwindow(int _size_x, int _size_y, int offset_x, int offset_y) +{ + window result; + result.win_ptr = subwin(win_ptr, _size_y, _size_x, offset_y, offset_x); + result.size_x = _size_x; + result.size_y = _size_y; + subwindows.push_back(result); + return result; +} diff --git a/src/rang.cpp b/src/rang.cpp index 23bb2b6..f876b44 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,19 +1,15 @@ -#include "rang.hpp" #include "buffer.hpp" -#include "window.hpp" +#include "console_io.hpp" #include -#include #include #include -#include -#include int main(int argc, char *argv[]) { - int width, height; - int ch; + int width; + int height; - initscr(); /* Start curses mode */ + console_io::ncurses root; start_color(); use_default_colors(); cbreak(); /* Line buffering disabled, Pass on @@ -23,8 +19,8 @@ int main(int argc, char *argv[]) height = LINES; width = COLS; - refresh(); - window mywin(width - 2, height - 2, 1, 1); + root.refresh(); + console_io::window mywin = root.subwindow(width - 2, height - 2, 1, 1); directory_listing lst("."); lst.update(); int current = 0; @@ -33,6 +29,5 @@ int main(int argc, char *argv[]) } mywin.refresh(); getch(); - endwin(); return 0; } From 629d678cac1169ced4e5b7a63464bb84b29bbf86 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 10 Dec 2020 11:34:17 +0300 Subject: [PATCH 13/24] new window abstraction --- include/buffer.hpp | 6 +----- include/rang.hpp | 10 ---------- include/rwindow.hpp | 21 +++++++++++++++++++++ src/CMakeLists.txt | 2 +- src/buffer.cpp | 5 ++--- src/rang.cpp | 10 ++++------ src/rwindow.cpp | 16 ++++++++++++++++ 7 files changed, 45 insertions(+), 25 deletions(-) delete mode 100644 include/rang.hpp create mode 100644 include/rwindow.hpp create mode 100644 src/rwindow.cpp diff --git a/include/buffer.hpp b/include/buffer.hpp index 1c962db..9a02e72 100644 --- a/include/buffer.hpp +++ b/include/buffer.hpp @@ -1,7 +1,6 @@ #ifndef __BUFFER_HPP #define __BUFFER_HPP -#include "rang.hpp" #include #include #include @@ -15,7 +14,7 @@ class buffer buffer() = default; - void update(); + virtual void update() = 0; }; class dummy : buffer @@ -24,9 +23,6 @@ class dummy : buffer class directory_listing : public buffer { - private: - fs::directory_iterator it; - public: fs::path directory; diff --git a/include/rang.hpp b/include/rang.hpp deleted file mode 100644 index 9ba244c..0000000 --- a/include/rang.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __RANG_HPP -#define __RANG_HPP - -#include - -namespace rang -{ -const std::string MESSAGE = "Hello, world\n"; -} -#endif diff --git a/include/rwindow.hpp b/include/rwindow.hpp new file mode 100644 index 0000000..7148f47 --- /dev/null +++ b/include/rwindow.hpp @@ -0,0 +1,21 @@ +#ifndef __NWINDOW_HPP +#define __NWINDOW_HPP + +#include "buffer.hpp" +#include "console_io.hpp" + +class window +{ + private: + console_io::window win; + buffer &tied_buf; + + public: + window(console_io::window &&_win, buffer &_tied_buf); + + void refresh(); + + void shift_viewport(int shift); +}; + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05d4cdd..91adbe4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(console_io) -add_executable (rang rang.cpp buffer.cpp) +add_executable (rang rang.cpp buffer.cpp rwindow.cpp) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} console_io) diff --git a/src/buffer.cpp b/src/buffer.cpp index 523cb2d..856bd45 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -1,15 +1,14 @@ #include "buffer.hpp" #include -#include directory_listing::directory_listing(fs::path _directory) : directory(_directory) { - it = fs::directory_iterator(directory); -}; +} void directory_listing::update() { std::vector filtered; + fs::directory_iterator it(directory); std::copy_if(fs::begin(it), fs::end(it), std::back_insert_iterator(filtered), [](fs::directory_entry entry) -> bool { return entry.path().filename().string().front() != '.'; diff --git a/src/rang.cpp b/src/rang.cpp index f876b44..af67caf 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,5 +1,6 @@ #include "buffer.hpp" #include "console_io.hpp" +#include "rwindow.hpp" #include #include #include @@ -16,18 +17,15 @@ int main(int argc, char *argv[]) * everty thing to me */ keypad(stdscr, TRUE); /* I need that nifty F1 */ noecho(); + curs_set(0); height = LINES; width = COLS; root.refresh(); console_io::window mywin = root.subwindow(width - 2, height - 2, 1, 1); directory_listing lst("."); - lst.update(); - int current = 0; - for (std::string &line : lst.contents) { - mywin.move_and_output(0, current++, line); - } - mywin.refresh(); + window main(std::move(mywin), lst); + main.refresh(); getch(); return 0; } diff --git a/src/rwindow.cpp b/src/rwindow.cpp new file mode 100644 index 0000000..ba76ac0 --- /dev/null +++ b/src/rwindow.cpp @@ -0,0 +1,16 @@ +#include "rwindow.hpp" + +window::window(console_io::window &&_win, buffer &_tied_buf) : win(_win), tied_buf(_tied_buf) +{ +} + +void window::refresh() +{ + tied_buf.update(); + for (int y = 0; y < win.size_y && y < tied_buf.contents.size(); ++y) { + std::string line = tied_buf.contents[y]; + line.resize(win.size_x, ' '); + win.move_and_output(0, y, line); + } + win.refresh(); +} From 01fcb87330264a3ec5ca1a0de46e3fc73739e7ae Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 10 Dec 2020 22:37:48 +0300 Subject: [PATCH 14/24] scrolling. exceptions --- include/rwindow.hpp | 3 ++- src/console_io/include/window.hpp | 2 ++ src/console_io/src/base.cpp | 5 +++++ src/console_io/src/window.cpp | 34 +++++++++++++++++++++++++------ src/rang.cpp | 34 ++++++++++++++++++++++++++----- src/rwindow.cpp | 19 ++++++++++++----- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/include/rwindow.hpp b/include/rwindow.hpp index 7148f47..1fd0224 100644 --- a/include/rwindow.hpp +++ b/include/rwindow.hpp @@ -11,11 +11,12 @@ class window buffer &tied_buf; public: + int offset_x = 0, offset_y = 0; window(console_io::window &&_win, buffer &_tied_buf); void refresh(); - void shift_viewport(int shift); + void scroll_viewport(int shift); }; #endif diff --git a/src/console_io/include/window.hpp b/src/console_io/include/window.hpp index 9ff1860..0f6f4f3 100644 --- a/src/console_io/include/window.hpp +++ b/src/console_io/include/window.hpp @@ -35,6 +35,8 @@ class window void move_and_output(int x, int y, std::string s); + void outputln(int y, std::string s); + window subwindow(int _size_x, int _size_y, int offset_x, int offset_y); }; } // namespace console_io diff --git a/src/console_io/src/base.cpp b/src/console_io/src/base.cpp index 2d4fc15..0cb34ca 100644 --- a/src/console_io/src/base.cpp +++ b/src/console_io/src/base.cpp @@ -6,6 +6,11 @@ using namespace console_io; ncurses::ncurses() { win_ptr = initscr(); + if (win_ptr == nullptr) { + throw 1; + } + size_x = COLS; + size_y = LINES; } ncurses::~ncurses() diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp index 4c40345..b8746dd 100644 --- a/src/console_io/src/window.cpp +++ b/src/console_io/src/window.cpp @@ -7,6 +7,9 @@ window::window(int _size_x, int _size_y, int offset_x, int offset_y, window *_pa : size_x(_size_x), size_y(_size_y), parent(_parent) { win_ptr = newwin(size_y, size_x, offset_y, offset_x); + if (win_ptr == nullptr) { + throw 1; // TODO errors + } refresh(); } @@ -29,30 +32,49 @@ bool window::operator==(const window &other) void window::refresh() { - wrefresh(win_ptr); + if (wrefresh(win_ptr) == ERR) { + throw 1; + }; } void window::move(int x, int y) { - wmove(win_ptr, y, x); + if (wmove(win_ptr, y, x) == ERR) { + throw 1; + }; } void window::output(std::string s) { - waddstr(win_ptr, s.c_str()); + if (waddstr(win_ptr, s.c_str()) == ERR) { + throw 1; + } } void window::move_and_output(int x, int y, std::string s) { - mvwaddstr(win_ptr, y, x, s.c_str()); + if (mvwaddstr(win_ptr, y, x, s.c_str()) == ERR) { + throw 1; + } +} + +void window::outputln(int y, std::string s) +{ + s.resize(size_x - 1, ' '); + if (mvwaddstr(win_ptr, y, 0, s.c_str()) == ERR) { + throw 1; + } } window window::subwindow(int _size_x, int _size_y, int offset_x, int offset_y) { window result; result.win_ptr = subwin(win_ptr, _size_y, _size_x, offset_y, offset_x); - result.size_x = _size_x; - result.size_y = _size_y; + if (result.win_ptr == nullptr) { + throw 1; + } + result.size_x = _size_x; + result.size_y = _size_y; subwindows.push_back(result); return result; } diff --git a/src/rang.cpp b/src/rang.cpp index af67caf..8339373 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -2,6 +2,7 @@ #include "console_io.hpp" #include "rwindow.hpp" #include +#include #include #include @@ -18,14 +19,37 @@ int main(int argc, char *argv[]) keypad(stdscr, TRUE); /* I need that nifty F1 */ noecho(); curs_set(0); - - height = LINES; - width = COLS; root.refresh(); - console_io::window mywin = root.subwindow(width - 2, height - 2, 1, 1); + console_io::window mywin = root.subwindow(root.size_x - 2, root.size_y - 2, 1, 1); directory_listing lst("."); + std::ofstream of("log.txt"); + of << "UPDATING..." << std::endl; + lst.update(); + of << "UPDATED." << std::endl; window main(std::move(mywin), lst); + root.refresh(); + of << "CREATED WINDOW" << std::endl; + int ch; main.refresh(); - getch(); + of << "REFRESHED" << std::endl; + while ((ch = getch()) != KEY_F(1)) { + try { + switch (ch) { + case 'j': + case KEY_DOWN: + main.scroll_viewport(1); + break; + case 'k': + case KEY_UP: + main.scroll_viewport(-1); + break; + } + root.outputln(root.size_y - 1, "OK"); + } catch (int) { + root.outputln(root.size_y - 1, "Error found"); + } + root.refresh(); + main.refresh(); + } return 0; } diff --git a/src/rwindow.cpp b/src/rwindow.cpp index ba76ac0..bad03dd 100644 --- a/src/rwindow.cpp +++ b/src/rwindow.cpp @@ -6,11 +6,20 @@ window::window(console_io::window &&_win, buffer &_tied_buf) : win(_win), tied_b void window::refresh() { - tied_buf.update(); - for (int y = 0; y < win.size_y && y < tied_buf.contents.size(); ++y) { - std::string line = tied_buf.contents[y]; - line.resize(win.size_x, ' '); - win.move_and_output(0, y, line); + for (int y = 0; y < win.size_y; ++y) { + if (offset_y + y < tied_buf.contents.size()) { + win.outputln(y, tied_buf.contents[offset_y + y]); + } else { + win.outputln(y, ""); + } } win.refresh(); } + +void window::scroll_viewport(int shift) +{ + if (offset_y + shift >= tied_buf.contents.size() || offset_y + shift < 0) { + throw 1; // todo errors + } + offset_y += shift; +} From c93400db902f023e3aa3d0630ec66fcafd31f0c2 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Wed, 16 Dec 2020 12:00:57 +0300 Subject: [PATCH 15/24] virtual destructor for buffer Signed-off-by: Pavel Kalugin --- include/buffer.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/buffer.hpp b/include/buffer.hpp index 9a02e72..dae3ece 100644 --- a/include/buffer.hpp +++ b/include/buffer.hpp @@ -14,6 +14,8 @@ class buffer buffer() = default; + virtual ~buffer() = default; + virtual void update() = 0; }; From 304253363a2a1c16f1c2d8339db2389573d25e48 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Wed, 16 Dec 2020 12:05:27 +0300 Subject: [PATCH 16/24] target-wide C++ standard Signed-off-by: Pavel Kalugin --- CMakeLists.txt | 3 --- src/CMakeLists.txt | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7776d29..8804a4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,6 @@ project(rang) set(CURSES_NEED_NCURSES TRUE) find_package(Curses REQUIRED) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED TRUE) - add_subdirectory(src) target_include_directories(rang PUBLIC include) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91adbe4..673236f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,5 +2,6 @@ add_subdirectory(console_io) add_executable (rang rang.cpp buffer.cpp rwindow.cpp) +target_compile_features(rang PUBLIC cxx_std_17) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} console_io) From 20b23df7c10e67ab0762fe8da0442d525bf5c3a7 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Wed, 16 Dec 2020 12:07:10 +0300 Subject: [PATCH 17/24] remove obsolete color initialization Signed-off-by: Pavel Kalugin --- src/rang.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/rang.cpp b/src/rang.cpp index 8339373..24ba137 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -12,8 +12,6 @@ int main(int argc, char *argv[]) int height; console_io::ncurses root; - start_color(); - use_default_colors(); cbreak(); /* Line buffering disabled, Pass on * everty thing to me */ keypad(stdscr, TRUE); /* I need that nifty F1 */ From 69b5ef7a944b12966405da370a5dd8271c9e83b7 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Mon, 28 Dec 2020 20:08:01 +0300 Subject: [PATCH 18/24] forbid modifying of size_x and size_y Signed-off-by: Pavel Kalugin --- src/console_io/include/window.hpp | 25 ++++++++++++++++--------- src/console_io/src/window.cpp | 28 ++++++++++++++++++++++------ src/rang.cpp | 13 ++++--------- src/rwindow.cpp | 2 +- 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/console_io/include/window.hpp b/src/console_io/include/window.hpp index 0f6f4f3..0423a8e 100644 --- a/src/console_io/include/window.hpp +++ b/src/console_io/include/window.hpp @@ -12,30 +12,37 @@ class window { protected: WINDOW *win_ptr = nullptr; + int size_x = 0; + int size_y = 0; + int offset_x = 0; + int offset_y = 0; public: - int size_x = 0; - int size_y = 0; window *parent = nullptr; std::vector subwindows; window() = default; - window(int _size_x, int _size_y, int offset_x, int offset_y, window *_parent = nullptr); + window(int _size_x, int _size_y, int _offset_x, int _offset_y, window *_parent = nullptr); ~window(); - bool operator==(const window &other); + bool operator==(const window &other) const; - void refresh(); + int get_size_x() const; + int get_size_y() const; + int get_offset_x() const; + int get_offset_y() const; - void move(int x, int y); + void refresh() const; - void output(std::string s); + void move(int x, int y) const; - void move_and_output(int x, int y, std::string s); + void output(std::string s) const; - void outputln(int y, std::string s); + void move_and_output(int x, int y, std::string s) const; + + void outputln(int y, std::string s) const; window subwindow(int _size_x, int _size_y, int offset_x, int offset_y); }; diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp index b8746dd..7597b5d 100644 --- a/src/console_io/src/window.cpp +++ b/src/console_io/src/window.cpp @@ -25,40 +25,56 @@ window::~window() delwin(win_ptr); } -bool window::operator==(const window &other) +bool window::operator==(const window &other) const { return win_ptr == other.win_ptr; } -void window::refresh() +int window::get_size_x() const { + return size_x; +} + +int window::get_size_y() const { + return size_y; +} + +int window::get_offset_x() const { + return offset_x; +} + +int window::get_offset_y() const { + return offset_y; +} + +void window::refresh() const { if (wrefresh(win_ptr) == ERR) { throw 1; }; } -void window::move(int x, int y) +void window::move(int x, int y) const { if (wmove(win_ptr, y, x) == ERR) { throw 1; }; } -void window::output(std::string s) +void window::output(std::string s) const { if (waddstr(win_ptr, s.c_str()) == ERR) { throw 1; } } -void window::move_and_output(int x, int y, std::string s) +void window::move_and_output(int x, int y, std::string s) const { if (mvwaddstr(win_ptr, y, x, s.c_str()) == ERR) { throw 1; } } -void window::outputln(int y, std::string s) +void window::outputln(int y, std::string s) const { s.resize(size_x - 1, ' '); if (mvwaddstr(win_ptr, y, 0, s.c_str()) == ERR) { diff --git a/src/rang.cpp b/src/rang.cpp index 24ba137..19c2152 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -2,7 +2,6 @@ #include "console_io.hpp" #include "rwindow.hpp" #include -#include #include #include @@ -18,18 +17,14 @@ int main(int argc, char *argv[]) noecho(); curs_set(0); root.refresh(); - console_io::window mywin = root.subwindow(root.size_x - 2, root.size_y - 2, 1, 1); + console_io::window mywin = + root.subwindow(root.get_size_x() - 2, root.get_size_y() - 2, 1, 1); directory_listing lst("."); - std::ofstream of("log.txt"); - of << "UPDATING..." << std::endl; lst.update(); - of << "UPDATED." << std::endl; window main(std::move(mywin), lst); root.refresh(); - of << "CREATED WINDOW" << std::endl; int ch; main.refresh(); - of << "REFRESHED" << std::endl; while ((ch = getch()) != KEY_F(1)) { try { switch (ch) { @@ -42,9 +37,9 @@ int main(int argc, char *argv[]) main.scroll_viewport(-1); break; } - root.outputln(root.size_y - 1, "OK"); + root.outputln(root.get_size_y() - 1, "OK"); } catch (int) { - root.outputln(root.size_y - 1, "Error found"); + root.outputln(root.get_size_y() - 1, "Error found"); } root.refresh(); main.refresh(); diff --git a/src/rwindow.cpp b/src/rwindow.cpp index bad03dd..fdb799e 100644 --- a/src/rwindow.cpp +++ b/src/rwindow.cpp @@ -6,7 +6,7 @@ window::window(console_io::window &&_win, buffer &_tied_buf) : win(_win), tied_b void window::refresh() { - for (int y = 0; y < win.size_y; ++y) { + for (int y = 0; y < win.get_size_y(); ++y) { if (offset_y + y < tied_buf.contents.size()) { win.outputln(y, tied_buf.contents[offset_y + y]); } else { From e5f148c1e10fc6d72445b262d6e8d4f040b38694 Mon Sep 17 00:00:00 2001 From: pavel-the-best Date: Mon, 28 Dec 2020 17:11:41 +0000 Subject: [PATCH 19/24] Apply formatting changes --- src/console_io/src/window.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp index 7597b5d..6560dcd 100644 --- a/src/console_io/src/window.cpp +++ b/src/console_io/src/window.cpp @@ -30,19 +30,23 @@ bool window::operator==(const window &other) const return win_ptr == other.win_ptr; } -int window::get_size_x() const { +int window::get_size_x() const +{ return size_x; } -int window::get_size_y() const { +int window::get_size_y() const +{ return size_y; } -int window::get_offset_x() const { +int window::get_offset_x() const +{ return offset_x; } -int window::get_offset_y() const { +int window::get_offset_y() const +{ return offset_y; } From 8c23f55eeac277cc55776ce5f7f30ff08d65dd9f Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 31 Dec 2020 15:18:39 +0300 Subject: [PATCH 20/24] event loop Signed-off-by: Pavel Kalugin --- include/buffer.hpp | 3 ++ include/evloop.hpp | 40 ++++++++++++++++++++++++++ include/rwindow.hpp | 7 +++-- src/CMakeLists.txt | 6 ++-- src/buffer.cpp | 2 ++ src/console_io/include/console_io.hpp | 2 ++ src/console_io/include/window.hpp | 2 ++ src/console_io/src/window.cpp | 5 ++++ src/evloop.cpp | 41 +++++++++++++++++++++++++++ src/rang.cpp | 39 ++++++++++++++----------- src/rwindow.cpp | 2 ++ 11 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 include/evloop.hpp create mode 100644 src/evloop.cpp diff --git a/include/buffer.hpp b/include/buffer.hpp index dae3ece..111cd6b 100644 --- a/include/buffer.hpp +++ b/include/buffer.hpp @@ -7,6 +7,8 @@ namespace fs = std::filesystem; +namespace rang +{ class buffer { public: @@ -32,4 +34,5 @@ class directory_listing : public buffer void update(); }; +} // namespace rang #endif diff --git a/include/evloop.hpp b/include/evloop.hpp new file mode 100644 index 0000000..71b2836 --- /dev/null +++ b/include/evloop.hpp @@ -0,0 +1,40 @@ +#ifndef __EVLOOP_HPP +#define __EVLOOP_HPP + +#include +#include +#include +#include + +#undef timeout + +namespace rang +{ +class event_loop +{ + private: + boost::asio::io_context io_context; + boost::asio::signal_set signals; + boost::asio::posix::stream_descriptor input; + + public: + event_loop(); + + template + void add_regular_job(const std::function callback, + const duration &interval); // TODO implementation + + template + void add_job(const std::function callback, time_point &time); // TODO implementation + + void set_input_reaction(const std::function callback); + + void run(); + + void stop(); + + private: + void handle_input(const std::function &callback); +}; +} // namespace rang +#endif diff --git a/include/rwindow.hpp b/include/rwindow.hpp index 1fd0224..e16d01b 100644 --- a/include/rwindow.hpp +++ b/include/rwindow.hpp @@ -1,9 +1,11 @@ -#ifndef __NWINDOW_HPP -#define __NWINDOW_HPP +#ifndef __RWINDOW_HPP +#define __RWINDOW_HPP #include "buffer.hpp" #include "console_io.hpp" +namespace rang +{ class window { private: @@ -18,5 +20,6 @@ class window void scroll_viewport(int shift); }; +} // namespace rang #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 673236f..d2b52ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,9 @@ add_subdirectory(console_io) -add_executable (rang rang.cpp buffer.cpp rwindow.cpp) +add_executable (rang evloop.cpp buffer.cpp rwindow.cpp rang.cpp) + +find_package(Boost 1.70.0 REQUIRED COMPONENTS system thread) target_compile_features(rang PUBLIC cxx_std_17) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS}) -target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} console_io) +target_link_libraries(rang PUBLIC ${CURSES_LIBRARIES} ${Boost_LIBRARIES} console_io) diff --git a/src/buffer.cpp b/src/buffer.cpp index 856bd45..6360f70 100644 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -1,6 +1,8 @@ #include "buffer.hpp" #include +using namespace rang; + directory_listing::directory_listing(fs::path _directory) : directory(_directory) { } diff --git a/src/console_io/include/console_io.hpp b/src/console_io/include/console_io.hpp index ba78c30..964638d 100644 --- a/src/console_io/include/console_io.hpp +++ b/src/console_io/include/console_io.hpp @@ -2,4 +2,6 @@ #define __CONSOLE_IO_HPP #include "base.hpp" #include "window.hpp" + +#undef timeout #endif diff --git a/src/console_io/include/window.hpp b/src/console_io/include/window.hpp index 0423a8e..8a41de0 100644 --- a/src/console_io/include/window.hpp +++ b/src/console_io/include/window.hpp @@ -45,6 +45,8 @@ class window void outputln(int y, std::string s) const; window subwindow(int _size_x, int _size_y, int offset_x, int offset_y); + + int set_keypad(bool value) const; }; } // namespace console_io diff --git a/src/console_io/src/window.cpp b/src/console_io/src/window.cpp index 6560dcd..3598dc1 100644 --- a/src/console_io/src/window.cpp +++ b/src/console_io/src/window.cpp @@ -98,3 +98,8 @@ window window::subwindow(int _size_x, int _size_y, int offset_x, int offset_y) subwindows.push_back(result); return result; } + +int window::set_keypad(bool value) const +{ + return keypad(win_ptr, (value ? TRUE : FALSE)); +} diff --git a/src/evloop.cpp b/src/evloop.cpp new file mode 100644 index 0000000..ab2df4a --- /dev/null +++ b/src/evloop.cpp @@ -0,0 +1,41 @@ +#include "evloop.hpp" +#include +#include + +#undef timeout + +using namespace rang; + +event_loop::event_loop() + : signals(io_context, SIGINT, SIGTERM), // handle SIGINT and SIGTERM signals + input(io_context, STDIN_FILENO) // take input from stdin stream +{ + signals.async_wait([&](auto, auto) { io_context.stop(); }); +} + +void event_loop::run() +{ + io_context.run(); +} + +void event_loop::stop() +{ + io_context.stop(); +} + +void event_loop::set_input_reaction(const std::function callback) +{ + input.cancel(); + handle_input(callback); +} + +void event_loop::handle_input(const std::function &callback) +{ + input.async_wait(boost::asio::posix::stream_descriptor::wait_read, + [this, callback](auto error) { + if (!error) { + callback(getch()); + } + handle_input(callback); + }); +} diff --git a/src/rang.cpp b/src/rang.cpp index 19c2152..c4ff2d3 100644 --- a/src/rang.cpp +++ b/src/rang.cpp @@ -1,5 +1,6 @@ #include "buffer.hpp" #include "console_io.hpp" +#include "evloop.hpp" #include "rwindow.hpp" #include #include @@ -7,42 +8,46 @@ int main(int argc, char *argv[]) { - int width; - int height; - console_io::ncurses root; - cbreak(); /* Line buffering disabled, Pass on - * everty thing to me */ - keypad(stdscr, TRUE); /* I need that nifty F1 */ + cbreak(); /* Line buffering disabled, Pass on + *everty thing to me */ + root.set_keypad(true); /* I need that nifty F1 */ + keypad(stdscr, TRUE); noecho(); curs_set(0); root.refresh(); console_io::window mywin = root.subwindow(root.get_size_x() - 2, root.get_size_y() - 2, 1, 1); - directory_listing lst("."); + rang::directory_listing lst("."); lst.update(); - window main(std::move(mywin), lst); + rang::window main(std::move(mywin), lst); root.refresh(); int ch; main.refresh(); - while ((ch = getch()) != KEY_F(1)) { + rang::event_loop loop; + std::function reaction_func = [&](int ch) { + if (ch == KEY_F(1)) { + loop.stop(); + return; + } try { switch (ch) { - case 'j': case KEY_DOWN: + case 'j': main.scroll_viewport(1); break; - case 'k': case KEY_UP: + case 'k': main.scroll_viewport(-1); break; + default: + return; } - root.outputln(root.get_size_y() - 1, "OK"); - } catch (int) { - root.outputln(root.get_size_y() - 1, "Error found"); + main.refresh(); + } catch (error_t) { } - root.refresh(); - main.refresh(); - } + }; + loop.set_input_reaction(reaction_func); + loop.run(); return 0; } diff --git a/src/rwindow.cpp b/src/rwindow.cpp index fdb799e..77dcc69 100644 --- a/src/rwindow.cpp +++ b/src/rwindow.cpp @@ -1,5 +1,7 @@ #include "rwindow.hpp" +using namespace rang; + window::window(console_io::window &&_win, buffer &_tied_buf) : win(_win), tied_buf(_tied_buf) { } From 8afbfc9ad27eea4cf5f8b44fc28a2b7b38a0e117 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 31 Dec 2020 15:36:18 +0300 Subject: [PATCH 21/24] fix github actions Signed-off-by: Pavel Kalugin --- .github/workflows/ci.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f653f75..1403bc8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,6 +16,9 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -yq libboost-all-dev + - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory # We'll use this as our working directory for all subsequent commands From 3094bdfece095c233bfb4da2085bd72a6f40c476 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 31 Dec 2020 15:37:57 +0300 Subject: [PATCH 22/24] fixup --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1403bc8..610c0d7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies - run: sudo apt-get update && sudo apt-get install -yq libboost-all-dev + run: apt-get update && apt-get install -yq libboost-all-dev - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory From a8ffa77eaea9a3ba58d4ac3d66833fff9ad90ec2 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 31 Dec 2020 15:39:57 +0300 Subject: [PATCH 23/24] fixup #2 --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 610c0d7..c2dc276 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies - run: apt-get update && apt-get install -yq libboost-all-dev + run: apt-get update && apt-get install -yq libboost-thread-dev libboost-system-dev - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory From e61246070da4e01e3f73ed3c777009dc5d6e81ca Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Thu, 31 Dec 2020 15:41:45 +0300 Subject: [PATCH 24/24] fix boost required version --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2b52ab..83ce58e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(console_io) add_executable (rang evloop.cpp buffer.cpp rwindow.cpp rang.cpp) -find_package(Boost 1.70.0 REQUIRED COMPONENTS system thread) +find_package(Boost 1.60.0 REQUIRED COMPONENTS system thread) target_compile_features(rang PUBLIC cxx_std_17) target_include_directories(rang PUBLIC ${CURSES_INCLUDE_DIRS})