https://github.com/e-dant/watcher Skip to content Toggle navigation Sign up * Product + Actions Automate any workflow + Packages Host and manage packages + Security Find and fix vulnerabilities + Codespaces Instant dev environments + Copilot Write better code with AI + Code review Manage code changes + Issues Plan and track work + Discussions Collaborate outside of code + Explore + All features + Documentation + GitHub Skills + Blog * Solutions + By Plan + Enterprise + Teams + Compare all + By Solution + CI/CD & Automation + DevOps + DevSecOps + Case Studies + Customer Stories + Resources * Open Source + GitHub Sponsors Fund open source developers + The ReadME Project GitHub community articles + Repositories + Topics + Trending + Collections * Pricing [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} e-dant / watcher Public * Notifications * Fork 6 * Star 172 Filesystem watcher. Works anywhere. Simple, efficient and friendly. License MIT license 172 stars 6 forks Star Notifications * Code * Issues 3 * Pull requests 0 * Discussions * Actions * Projects 0 * Security * Insights More * Code * Issues * Pull requests * Discussions * Actions * Projects * Security * Insights e-dant/watcher This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. release Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags Name already in use A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch? Cancel Create 2 branches 10 tags Code * Clone HTTPS GitHub CLI [https://github.com/e] Use Git or checkout with SVN using the web URL. [gh repo clone e-dant] Work fast with our official CLI. Learn more. * Open with GitHub Desktop * Download ZIP Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Launching Xcode If nothing happens, download Xcode and try again. Launching Visual Studio Code Your codespace will open once ready. There was a problem preparing your codespace, please try again. Latest commit Will release: 0.2.9 ... 989147b Oct 18, 2022 release: 0.2.9 989147b Git stats * 177 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .github/workflows github/workflows: noenv + noinstall Oct 18, 2022 .hooks hooks/pre-commit: safety Oct 17, 2022 build release: 0.2.9 Oct 18, 2022 include watch: cast on windows Oct 18, 2022 sinclude watch: cast on windows Oct 18, 2022 src src/tiny-main: a few comments are fine + doc Oct 18, 2022 tool tool/release: syntax Oct 18, 2022 .clang-format clang-format: simple Oct 18, 2022 .gitignore gitignore: ws Oct 18, 2022 .lgtm.yml lgtm Oct 17, 2022 .tellfile tell/dbun + darwin/safety Sep 25, 2022 .version release: 0.2.9 Oct 18, 2022 LICENSE license: cap Oct 18, 2022 README.md src/tiny-main: a few comments are fine + doc Oct 18, 2022 View code [ ] Watcher Quick Start Tell Me More Usage Important Files The Library Your Project Consume In Your Project As A CLI Program Tell CMake Notes [1] Exceptions to Efficient Scanning README.md Watcher CodeQL Linux MacOS Windows Quick Start Write: /* tiny-main.cpp */ #include #include "../sinclude/watcher/watcher.hpp" /* Point this to wherever yours is */ int main(int argc, char** argv) { using water::watcher::event::event, water::watcher::watch, std::cout, std::endl; cout << R"({"water.watcher.stream":{)" << endl; /* This is the important line. */ const auto is_watch_ok = watch<16>( argc > 1 ? argv[1] : ".", [](const event& this_event) { cout << this_event << ',' << endl; }); cout << '}' << endl << '}' << endl; return is_watch_ok; } Compile & Run: g++ -std=c++2a src/tiny-main.cpp -o watch ./watch Enjoy! Tell Me More An arbitrary filesystem event watcher which is: * simple * efficient * dependency free * runnable anywhere * header only Watcher is extremely efficient. In most cases, even when scanning millions of paths, this library uses a near-zero amount of resources. [1] If you don't want to use it in another project, don't worry. It comes with one. Just build and run and you've got yourself a filesystem watcher which prints filesystem events as JSON, which is pretty cool. You could, for example, run this program, await events, and filter through the noise: # get git clone https://github.com/e-dant/watcher.git && cd watcher # build cmake -S build/in -B build/out && cmake --build build/out --config Release # or, from with the "water" project: `tell build` # use build/out/water.watcher | grep -oE 'needle-in-a-haystack/.+"' Watcher is trivially easy to use, include, and run. (I hope. If not, let me know.) Usage Note: If anything is unclear, make an issue about it! For deeper information, please see the headers. They are well-documented and are intended to be approachable. Important Files * watcher.hpp: Public interface. Someday, this will be a module. * main.cpp: Build this to use it as a CLI program. The Library Copy the include or sinclude (for the single header) into your project. Include as: #include After that, there are two things the user needs: * The watch function * The event structure watch takes a path, which is a string-like thing, and a callback, with is a function-like thing. event is an object used to pass information about filesystem events to watch. The event object will contain the: * Path -- Which is always relative. * Path type -- one of: + File + Directory + Symbolic Link + Hard Link + Unknown * Event type -- one of: + Create + Modify + Destroy + OS-Specific Events + Unknown * Event time -- In nanoseconds since epoch So, passing watch a string and a lambda would work well. watch will happily continue watching until it is asked to stop or it hits an unrecoverable error. Your Project It is trivial to build programs that yield something useful. Here is a snapshot of the output taken while preparing this commit, right before writing this paragraph. "water.watcher.stream": { "1663556133054707000": { "where": "water/watcher/.git/objects/cc/tmp_obj_sfbyd6", "what": "destroy", "kind": "other" }, "1663556133054710000": { "where": "water/watcher/.git/HEAD.lock", "what": "create", "kind": "other" }, "1663556133054713000": { "where": "water/watcher/.git/refs/heads/next.lock", "what": "create", "kind": "other" }, "1663556133054716000": { "where": "water/watcher/.git/refs/heads/next.lock", "what": "modify", "kind": "other" }, "1663556133069940000": { "where": "water/watcher/.git/logs/HEAD", "what": "modify", "kind": "file" } } Which is pretty cool. A main program suitable for this task: #include /* std::cout, std::endl */ #include /* water::watcher::watch, water::watcher::event */ /* Watch a path, forever. Stream what happens. Print every 16ms. */ int main(int argc, char** argv) { using water::watcher::event::event, water::watcher::watch, std::cout, std::endl; cout << R"({"water.watcher.stream":{)" << endl; /* Use the path we were given or the current directory. */ const auto path = argc > 1 ? argv[1] : "."; /* Show what happens. Format as json. Use event's stream operator. */ const auto show_event_json = [](const event& this_event) { cout << this_event << ',' << endl; }; /* Tick every 16ms. */ static constexpr auto delay_ms = 16; /* Run forever. */ const auto is_watch_ok = watch(path, show_event_json); cout << '}' << endl << '}' << endl; return is_watch_ok; } Consume In Your Project Download this project. Include watcher.hpp. That's all. This is a FetchContent-able project, if you're into that kind of thing. As A CLI Program Tell cd water/water/watcher `tell build` # watches the current directory `tell run` # watches some path # `tell run` your/favorite/path # or, to do all of the above: # `tell bun` your/favorite/path This will take care of: * Building a compiler if one is not found * Linking the compile_commands.json file to this project's root * Actually building the project CMake cd water/water/watcher/build cmake -S 'in' -B 'out' -G 'Ninja' -Wno-dev cmake --build out --config Release cd out # watches the current directory ./water.watcher # watches some path # ./water.watcher 'your/favorite/path' Notes [1] Exceptions to Efficient Scanning There are two cases where Watcher's efficiency takes a hit: 1. When the platform-independant warthog adapter is used. This happens on platforms which lack better alternatives, such as BSD and Solaris (warthog beats kqueue). 2. On embedded systems (where resources matter regardless). Watcher is still efficient in these cases. However, depending on your hardware and whether you need to watch 10-million paths or not, a longer delay_ms (such as in the seconds-range) might be necessary to prevent your machine from entering-the-atmosphere temperature. In all cases, this is a best-in-class filesystem watcher. The warthog is a capable watcher. About Filesystem watcher. Works anywhere. Simple, efficient and friendly. Topics fast cpp simple filesystem modern-cpp efficient header-only watcher friendly single-header cpp20 Resources Readme License MIT license Stars 172 stars Watchers 1 watching Forks 6 forks Languages * C++ 89.5% * Shell 9.5% * Other 1.0% Footer (c) 2022 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.