diff --git a/README.md b/README.md index 429fe1e..8cbf982 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,27 @@ -# i3switch – Multi-language Implementations +# i3switch - Intuitive i3 Window Switching Utility -The project started due to personal frustration with i3 window manager's switching controls, -and ideas for improving the experience. The most notable issues were: +We pick tiled window managers to improve our productivity. They allow us to lay out the workspace +in a way that we can see all the necessary information at a glance. This is the superpower of +tiled window managers. And the switching mechanism should follow this mindset. We want to switch +quickly to our layed out windows quickly, intuitively and efficiently. -- To switch tabs, You had to select the parent container (sometimes multiple times), - which, while deterministic, was cumbersome and dated. -- Direction based switching would often lead to unexpected results, especially with - multiple containers. -- Often, when switching directionally, the focus would jump to a hidden container, namely - tabs and stack containers, which would lead to confusion and frustration. +This is what i3switch is all about. It allows You to switch to what You see, without the necessary +abstraction of the manual tiling structure. -The first issue was the easiest to solve, as You could search i3 tree for the focused window -and find the parent tabbed container. This is the feature that I was using since I've started -the project and never looked back. +For more history and motivation, see [history.md](docs/history.md). -The second and third issues required consideration of multiple display setups, and -understanding of i3 tree structure quirks, which is not exactly intuitive. However, -this is understandable, due to the architecture of i3 and all of its features. +## Preview -## Multiple languages +[![Preview Video](https://raw.githubusercontent.com/mibli/i3switch/main/docs/media/preview.gif)](https://raw.githubusercontent.com/mibli/i3switch/main/docs/media/preview.mp4) -With interest in developing my skills I've decided to implement the same functionality -in multiple languages: Python, C++, and Rust. Each implementation has its own strengths and -weaknesses, and serves as a learning experience for both the developer and users. +## Features -Due to the nature of multiple implementations, it's infeasible to expect to maintain -exact similarity and feature parity across all languages. Consider **Rust implementation as the most -complete** and feature-rich, with C++ being the second, and Python as a reference implementation. - -### Why Multiple Languages? - -- **Educational value**: Demonstrates tradeoffs and idioms across ecosystems. -- **Practical insight**: Shows why certain languages are more suitable for certain tasks (e.g., startup time, memory use). -- **Portfolio**: Demonstrates adaptability and cross-language expertise. - -## Project Structure - -``` -i3switch/ -├── python/ # Python implementation -├── cpp/ # C++ implementation -├── rust/ # Rust implementation -├── scripts/ # Shared scripts (e.g., changelog generation, builds) -├── .github/ -│ └── workflows/ # CI/CD automation (changelog, builds, releases) -└── README.md # This file -``` - -Each implementation is self-contained, with its own dependencies, build instructions, and documentation. +* **Directional Switching**: Switch to the next window VISIBLE window in the specified direction. +* **Tab Navigation**: Switch to the next window in the current tabbed container. +* **Tab Number Switching**: Switch to the specified tab number in the current tabbed container. +* **Floating Switching**: Switch between floating windows in the direction or windows-like tab + navigation. +* **Multi-Monitor Support**: Switch windows across multiple monitors, respecting their layout. ## Building & Running @@ -72,54 +46,28 @@ make rust/dist/CHANGELOG.md **Proper binary versioning require .git repository to be present and tags to be fetched.** ---- +## Project Structure -## Language Notes & Motivation - -### Python - -Initial implementation in Python resembled the current i3switch, however after trying to use it -in i3, it was found to be **too slow** for frequent CLI invocation. The new Python implementation -relies on i3-msg calls for switching and tries to bind shortcuts, to run as a background daemon. -This implementation didn't allow for much flexibility in terms of i3 configuration, so it was -decided to implement the same functionality in C++. - -- Fastest for prototyping and learning. -- **Not optimal for frequent CLI invocation** due to slow startup (e.g., for i3 utilities). -- Maintained as a reference implementation and for language comparison. -- Great portability and dependency management. -- Distribution requires Python interpreter and dependencies, which may not be available in all - environments. - -### C++ - -This was the first implementation that was **fast enough** for frequent CLI invocation. It required -a major restructuring that allowed for proper geometric based window switching. To ensure it's -responsiveness, it implements it's own i3 tree navigation, that's designed to reduce copying and -allocation overhead. - -- Near-instant startup, low memory, suitable for system utilities. -- Classic choice for high-performance, resource-sensitive tasks. -- Available in most environments, making it easy to integrate. -- Requires careful memory management, but provides fine-grained control over performance. -- Implies mindfulness about dependencies and portability, as it may not be available in all - environments. -- Distribution requires C++ libraries, which may not be available in all environments. - -### Rust - -The Rust implementation was added to explore modern systems programming paradigms and memory safety. -It tightly resembles the C++ implementation, but uses Rust's ownership model to ensure memory -safety. Additionally the simplicity of Rust testing and build system allowed to find and fix -long prominent bugs present in the C++ implementation. - -- Modern, memory-safe, zero-cost abstraction. -- Comparable performance to C++, with additional compile-time safety. -- Great for learning Rust's systems programming features. -- Excellent for building robust, strongly tested applications. -- Crates enable robust system for extending language capabilities, which encourages small, focused - libraries. -- Distribution can be simplified with Cargo, but requires Rust toolchain to be installed. +``` +i3switch/ +├── python/ # Python implementation +├── cpp/ # C++ implementation +├── rust/ # Rust implementation +├── scripts/ # Shared scripts (e.g., changelog generation, builds) +├── .github/ +│ └── workflows/ # CI/CD automation (changelog, builds, releases) +└── README.md # This file +``` + +Each implementation is self-contained, with its own dependencies, build instructions, and documentation. + +## Getting Started + +See each subdirectory for build/run instructions: + +- [python/README.md](python/README.md) +- [cpp/README.md](cpp/README.md) +- [rust/README.md](rust/README.md) --- @@ -154,15 +102,11 @@ git cliff --config=/cliff.toml --output CHANGELOG.md - **Description**: lowercase summary of the change in the imperative mood - **Example**: `feat(py): support config files` ---- - -## Getting Started +## Branches -See each subdirectory for build/run instructions: - -- [python/README.md](python/README.md) -- [cpp/README.md](cpp/README.md) -- [rust/README.md](rust/README.md) +- **Main Branch**: `main` (contains the latest stable code) +- **Development Branches**: start with intent (feature/, bugfix/, etc.) and describe the change + - **Example**: `feature/add-new-switching-mode`, `bugfix/fix-memory-leak` --- diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 0000000..a13e90a --- /dev/null +++ b/docs/history.md @@ -0,0 +1,82 @@ +# i3switch Project History + +The project started due to personal frustration with i3 window manager's switching controls, +and ideas for improving the experience. The most notable issues were: + +- To switch tabs, You had to select the parent container (sometimes multiple times), + which, while deterministic, was cumbersome and dated. +- Direction based switching would often lead to unexpected results, especially with + multiple containers. +- Often, when switching directionally, the focus would jump to a hidden container, namely + tabs and stack containers, which would lead to confusion and frustration. + +The first issue was the easiest to solve, as You could search i3 tree for the focused window +and find the parent tabbed container. This is the feature that I was using since I've started +the project and never looked back. + +The second and third issues required consideration of multiple display setups, and +understanding of i3 tree structure quirks, which is not exactly intuitive. However, +this is understandable, due to the architecture of i3 and all of its features. + +## Multiple languages + +With interest in developing my skills I've decided to implement the same functionality +in multiple languages: Python, C++, and Rust. Each implementation has its own strengths and +weaknesses, and serves as a learning experience for both the developer and users. + +Due to the nature of multiple implementations, it's infeasible to expect to maintain +exact similarity and feature parity across all languages. Consider **Rust implementation as the most +complete** and feature-rich, with C++ being the second, and Python as a reference implementation. + +### Why Multiple Languages? + +- **Educational value**: Demonstrates tradeoffs and idioms across ecosystems. +- **Practical insight**: Shows why certain languages are more suitable for certain tasks (e.g., startup time, memory use). +- **Portfolio**: Demonstrates adaptability and cross-language expertise. + +## Language Notes & Motivation + +### Python + +Initial implementation in Python resembled the current i3switch, however after trying to use it +in i3, it was found to be **too slow** for frequent CLI invocation. The new Python implementation +relies on i3-msg calls for switching and tries to bind shortcuts, to run as a background daemon. +This implementation didn't allow for much flexibility in terms of i3 configuration, so it was +decided to implement the same functionality in C++. + +- Fastest for prototyping and learning. +- **Not optimal for frequent CLI invocation** due to slow startup (e.g., for i3 utilities). +- Maintained as a reference implementation and for language comparison. +- Great portability and dependency management. +- Distribution requires Python interpreter and dependencies, which may not be available in all + environments. + +### C++ + +This was the first implementation that was **fast enough** for frequent CLI invocation. It required +a major restructuring that allowed for proper geometric based window switching. To ensure it's +responsiveness, it implements it's own i3 tree navigation, that's designed to reduce copying and +allocation overhead. + +- Near-instant startup, low memory, suitable for system utilities. +- Classic choice for high-performance, resource-sensitive tasks. +- Available in most environments, making it easy to integrate. +- Requires careful memory management, but provides fine-grained control over performance. +- Implies mindfulness about dependencies and portability, as it may not be available in all + environments. +- Distribution requires C++ libraries, which may not be available in all environments. + +### Rust + +The Rust implementation was added to explore modern systems programming paradigms and memory safety. +It tightly resembles the C++ implementation, but uses Rust's ownership model to ensure memory +safety. Additionally the simplicity of Rust testing and build system allowed to find and fix +long prominent bugs present in the C++ implementation. + +- Modern, memory-safe, zero-cost abstraction. +- Comparable performance to C++, with additional compile-time safety. +- Great for learning Rust's systems programming features. +- Excellent for building robust, strongly tested applications. +- Crates enable robust system for extending language capabilities, which encourages small, focused + libraries. +- Distribution can be simplified with Cargo, but requires Rust toolchain to be installed. diff --git a/docs/media/preview.gif b/docs/media/preview.gif new file mode 100644 index 0000000..8449ffd Binary files /dev/null and b/docs/media/preview.gif differ diff --git a/docs/media/preview.mp4 b/docs/media/preview.mp4 new file mode 100644 index 0000000..df17b86 Binary files /dev/null and b/docs/media/preview.mp4 differ