├── .github ├── CODE_OF_CONDUCT.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── SECURITY.md ├── pull_request_template.md └── workflows │ ├── build-clipboard.yml │ ├── clipboard-website.yml │ ├── lint-clipboard.yml │ ├── test-clipboard.yml │ └── test-installer.yml ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LEARN.md ├── LICENSE ├── README.md ├── app.getclipboard.Clipboard.desktop ├── app.getclipboard.Clipboard.metainfo.xml ├── app.getclipboard.Clipboard.png ├── app.getclipboard.Clipboard.yml ├── build └── .gitignore ├── documentation ├── completions │ ├── cb.bash │ ├── cb.fish │ └── cb.zsh ├── fonts │ ├── lobster_two │ │ ├── LobsterTwo-Bold.ttf │ │ ├── LobsterTwo-BoldItalic.ttf │ │ ├── LobsterTwo-Italic.ttf │ │ ├── LobsterTwo-Regular.ttf │ │ └── OFL.txt │ ├── permanent_marker │ │ ├── LICENSE.txt │ │ └── PermanentMarker-Regular.ttf │ └── pt_sans │ │ ├── OFL.txt │ │ ├── PTSans-Bold.ttf │ │ └── PTSans-Regular.ttf ├── manpages │ ├── man.1 │ └── man.md ├── readme-assets │ ├── AllExceptWindows.png │ ├── AllExceptWindows.svg │ ├── CB.png │ ├── CB.svg │ ├── CBBanner.png │ ├── CBBanner.svg │ ├── CBBannerGitHub.jpg │ ├── CBBannerGitHub.svg │ ├── CBDemo.png │ ├── CBHowToUse.png │ ├── CBHowToUse.xcf │ ├── CBQuickInstallation.png │ ├── CBQuickInstallation.xcf │ ├── CBSimpleConfiguration.png │ ├── CBSimpleConfiguration.xcf │ ├── CBThemes.png │ ├── ClipboardDemo.gif │ ├── ClipboardMakesYourLifeEasy.png │ ├── ClipboardMakesYourLifeEasy.svg │ ├── CustomizeClipboard.png │ ├── CustomizeClipboard.svg │ ├── EnvironmentVariables.png │ ├── EnvironmentVariables.svg │ ├── Examples.png │ ├── Examples.svg │ ├── Features.png │ ├── Features.svg │ ├── Flags.png │ ├── Flags.svg │ ├── GetItOnGitHub.png │ ├── GetItOnGitHub.svg │ ├── GetStartedBelow.png │ ├── GetStartedBelow.svg │ ├── HowToUsePrompt.png │ ├── HowToUsePrompt.svg │ ├── InstallManually.png │ ├── InstallManually.svg │ ├── MoveThingsAround.png │ ├── MoveThingsAround.svg │ ├── NeedHelp.png │ ├── NeedHelp.xcf │ ├── PremadeBuilds.png │ ├── PremadeBuilds.svg │ ├── ProductivityTools.png │ ├── ProductivityTools.svg │ ├── SeeEverything.png │ ├── SeeEverything.svg │ ├── ThankYou.png │ ├── ThankYou.xcf │ ├── TheBasics.png │ ├── TheBasics.svg │ ├── TipsAndTricks.png │ ├── TipsAndTricks.svg │ ├── Uninstall.png │ ├── Uninstall.svg │ ├── WindowsRunAsAdmin.png │ ├── WindowsRunAsAdmin.svg │ ├── cb.tape │ ├── clipboard.svg │ ├── eyecandy.svg │ └── join-our-discord.svg └── website │ ├── config.toml │ ├── content │ ├── _docs.md │ └── _index.md │ ├── static │ ├── .well-known │ │ └── org.flathub.VerifiedApps.txt │ ├── CBBannerGitHub.jpg │ ├── ClipboardDemo.gif │ ├── LiveTerminalDemo.png │ ├── LobsterTwo-Bold.ttf │ ├── LobsterTwo-BoldItalic.ttf │ ├── OFL.txt │ ├── cb_small.png │ ├── demo.png │ └── get_it_on_github.png │ ├── templates │ ├── index.html │ └── page.html │ └── themes │ └── juice │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── config.toml │ ├── content │ ├── _index.md │ ├── about.md │ ├── changelog.md │ ├── exclude_from_nav.md │ ├── favicon.ico │ ├── juice.svg │ └── showcases.md │ ├── sass │ ├── _markdown.scss │ ├── _text.scss │ ├── _ultility.scss │ └── juice.scss │ ├── screenshot.png │ ├── static │ └── normalize.css │ ├── templates │ ├── _macros.html │ ├── _variables.html │ ├── index.html │ ├── page.html │ └── shortcodes │ │ └── issue.html │ ├── theme.toml │ └── vercel.json ├── install.ps1 ├── install.sh ├── justfile ├── snapcraft.yaml └── src ├── .clang-format ├── cb ├── CMakeLists.txt └── src │ ├── actions │ ├── add.cpp │ ├── clear.cpp │ ├── config.cpp │ ├── copy.cpp │ ├── edit.cpp │ ├── export.cpp │ ├── help.cpp │ ├── history.cpp │ ├── ignore.cpp │ ├── import.cpp │ ├── info.cpp │ ├── load.cpp │ ├── note.cpp │ ├── paste.cpp │ ├── pipeinout.cpp │ ├── redo.cpp │ ├── remove.cpp │ ├── script.cpp │ ├── search.cpp │ ├── share.cpp │ ├── show.cpp │ ├── status.cpp │ ├── swap.cpp │ └── undo.cpp │ ├── clipboard.cpp │ ├── clipboard.hpp │ ├── externalclipboards.cpp │ ├── indicator.cpp │ ├── locales │ ├── de_de.cpp │ ├── en_us.cpp │ ├── es_co.cpp │ ├── es_do.cpp │ ├── fr_fr.cpp │ ├── pt_br.cpp │ └── tr_tr.cpp │ ├── main.cpp │ ├── platforms │ ├── android.cpp │ ├── bsd.cpp │ ├── haiku.cpp │ ├── linux.cpp │ ├── macos.mm │ ├── windows.cpp │ ├── windows.hpp │ ├── windows.manifest │ └── x11wl.cpp │ ├── sounds │ ├── error.hpp │ ├── error.pcm │ ├── error.wav │ ├── success.hpp │ ├── success.pcm │ └── success.wav │ ├── themes.cpp │ └── utils │ ├── cowcopy.cpp │ ├── directorysize.cpp │ ├── distance.cpp │ ├── editors.cpp │ ├── files.cpp │ ├── formatting.cpp │ └── utils.cpp ├── cbwayland ├── CMakeLists.txt └── src │ ├── exception.hpp │ ├── fd.cpp │ ├── fd.hpp │ ├── objects │ ├── all.hpp │ ├── buffer.cpp │ ├── buffer.hpp │ ├── callback.cpp │ ├── callback.hpp │ ├── compositor.hpp │ ├── data_device.cpp │ ├── data_device.hpp │ ├── data_device_manager.hpp │ ├── data_offer.cpp │ ├── data_offer.hpp │ ├── data_source.cpp │ ├── data_source.hpp │ ├── display.cpp │ ├── display.hpp │ ├── forward.hpp │ ├── keyboard.cpp │ ├── keyboard.hpp │ ├── registry.cpp │ ├── registry.hpp │ ├── seat.cpp │ ├── seat.hpp │ ├── shm.cpp │ ├── shm.hpp │ ├── shm_pool.cpp │ ├── shm_pool.hpp │ ├── spec.hpp │ ├── surface.cpp │ ├── surface.hpp │ ├── xdg_surface.cpp │ ├── xdg_surface.hpp │ ├── xdg_toplevel.cpp │ ├── xdg_toplevel.hpp │ ├── xdg_wm_base.cpp │ └── xdg_wm_base.hpp │ └── wayland.cpp ├── cbx11 ├── CMakeLists.txt └── src │ └── x11.cpp ├── clang-format-check.ps1 ├── clang-format-check.sh ├── clang-format.ps1 ├── clang-format.sh ├── gui ├── CMakeLists.txt ├── include │ ├── all │ │ └── clipboard │ │ │ ├── fork.hpp │ │ │ ├── gui.hpp │ │ │ ├── logging.hpp │ │ │ └── utils.hpp │ └── x11wl │ │ └── clipboard │ │ └── x11wl │ │ └── mime.hpp └── src │ ├── fork.cpp │ ├── gui.cpp │ ├── inferextension.cpp │ ├── infermime.cpp │ ├── utils.cpp │ └── x11wl │ └── mime.cpp ├── shellcheck.sh └── tests ├── Exosphere 2.0.mp3 ├── TurnYourClipboardUp.png ├── add-file.sh ├── add-pipe.sh ├── add-text.sh ├── bad-action.sh ├── clear-file.sh ├── clear-pipe.sh ├── clear-text.sh ├── copy-file.sh ├── copy-pipe.sh ├── copy-text.sh ├── cut-file.sh ├── cut-pipe.sh ├── cut-text.sh ├── edit.sh ├── export.sh ├── help.sh ├── history.sh ├── ignore.sh ├── languages.sh ├── note-pipe.sh ├── note-text.sh ├── paste-file.sh ├── paste-pipe.sh ├── paste-text.sh ├── remove-file.sh ├── remove-pipe.sh ├── remove-text.sh ├── resources.sh ├── show-file.sh ├── show-pipe.sh ├── show-text.sh ├── status.sh ├── suite.sh ├── themes.sh ├── wayland.sh └── x11.sh /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [Slackadays] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Include the steps to reproduce your bug here. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Version** 23 | The version of CB you're using, how you got it, and what system you're using. 24 | Ex: I'm using CB 0.42.0 from the Arch repos with AmogOS. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | 29 | **Before you post** 30 | Please make sure you check previous bug reports before filing a new one. 31 | This will help keep the Issues section less cluttered. :) 32 | Feel free to delete this section once you've completed this form. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | Latest commit/release | :white_check_mark: | 8 | | Not latest commit/release | :x: | 9 | 10 | ## Reporting a Vulnerability 11 | 12 | If you find a vulnerability that is not the result of user error, email the authors or report it in the GitHub Security section. 13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Pull Request Requirements 2 | 3 | We're always accepting pull requests for contributions to the Clipboard Project. 4 | To keep quality high and the PRs flowing smoothly, we have three very simple rules that all PRs must follow. 5 | 6 | ### Use The Existing Code Style 7 | 8 | All code PRs must follow a similar code style to that of the existing code, unless the PR is about the code style itself. Try the `clang-format.sh` and `clang-format.ps1` scripts to use our code style in one step! 9 | 10 | ### Must Be Feature-Complete 11 | 12 | All PRs must be "feature complete." This means that you can't replace a feature with a TODO or remove it altogether, unless the PR is all about mofifying that feature. 13 | 14 | # Thanks for your contributions! 👋 15 | 16 | Replace all this text with your PR after you've reviewed it. 17 | -------------------------------------------------------------------------------- /.github/workflows/clipboard-website.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Clipboard Website 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | #- name: Fetch theme 34 | # uses: actions/checkout@v4 35 | # with: 36 | # repository: huhu/juice 37 | # path: documentation/website/themes/juice 38 | - name: Install Zola 39 | uses: taiki-e/install-action@v2 40 | with: 41 | tool: zola@0.17.2 42 | - name: Build content 43 | run: zola build 44 | working-directory: ./documentation/website 45 | - name: Setup Pages 46 | uses: actions/configure-pages@v2 47 | - name: Upload artifact 48 | uses: actions/upload-pages-artifact@v1 49 | with: 50 | # Upload entire repository 51 | path: 'documentation/website/public/' 52 | - name: Deploy to GitHub Pages 53 | id: deployment 54 | uses: actions/deploy-pages@v1 55 | -------------------------------------------------------------------------------- /.github/workflows/lint-clipboard.yml: -------------------------------------------------------------------------------- 1 | name: Clipboard Linting 2 | 3 | on: [ push, pull_request ] 4 | jobs: 5 | clang-format: 6 | runs-on: ubuntu-22.04 7 | 8 | steps: 9 | - uses: actions/checkout@v4 10 | 11 | - name: clang-format 12 | run: | 13 | sudo apt-get update 14 | sudo apt-get install -y clang-format-15 15 | 16 | sh src/clang-format-check.sh 17 | shellcheck: 18 | runs-on: ubuntu-22.04 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: shellcheck 24 | run: | 25 | sudo apt-get update 26 | sudo apt-get install -y shellcheck 27 | 28 | sh src/shellcheck.sh 29 | psscriptanalyzer: 30 | runs-on: windows-latest 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - name: psscriptanalyzer 36 | run: | 37 | Install-Module -Name PSScriptAnalyzer -Force 38 | Invoke-ScriptAnalyzer -Path install.ps1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | .cache/ 4 | .flatpak-builder/ 5 | Exported_Clipboards/ 6 | CMakeFiles/ 7 | 8 | src/tests/test_* 9 | 10 | *.flatpak 11 | *.snap 12 | 13 | build/* 14 | 15 | repo/* 16 | 17 | build-dir/* 18 | 19 | documentation/website/public/ 20 | 21 | gmon.out 22 | 23 | /temp/* -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Thanks for contributing to the Clipboard Project! 👋 2 | 3 | Thanks for your interest in contributing to Clipboard! We welcome all types of contributions including code, documentation, bug reports, feature requests, and general suggestions for improving the project. 4 | 5 | ## Guidelines for your valuable contributions 6 | 7 | 1. Attribution 8 | Please properly attribute your contributors. When submitting your pull request, please include: 9 | - Detailed explanations of your changes 10 | - References to relevant issues or discussions 11 | - Clear attributions to other authors if your changes incorporate their work 12 | 13 | 2. Separate Pull Requests 14 | Please keep unrelated additions or modifications in separate PRs. This is to allow us to focus on each change individually and provide feedback or action faster. 15 | 16 | 3. Code Formatting and Standards 17 | Before submitting any code changes please ensure you: 18 | - Run our provided formatting scripts to ensure consistency within the codebase. 19 | - Pass all automated tests by running the test suite locally. 20 | 21 | 4. Testing and Quality Assurance 22 | - When submitting code changes, please include relevant tests to help maintain the integrity of the project and ensure you don't introduce bugs. 23 | 24 | Getting Started 25 | 1. Fork the repository. 26 | 2. Clone the fork onto your local machine. 27 | 3. Create a new branch for your changes. 28 | 4. Make your changes and commit with meaningful messages 29 | 5. Run the test suite and formatting scripts 30 | 6. Submit your PR! 31 | -------------------------------------------------------------------------------- /LEARN.md: -------------------------------------------------------------------------------- 1 | # How I Made the Clipboard Project 2 | 3 | I made the Clipboard Project (which I'll call CB here) by first starting with something really small and simple but functional, then adding features upon features until I got to where it is right now. 4 | 5 | The Ugly Details: 6 | 7 | 1. First, I started by thinking about how I wanted CB to work in the first place. Because if I don't know what I want the final product to be, then I can't work towards anything. One huge, and HUGE, assumption I made was that every single time you use CB, it should only 8 | perform a single, atomic action. There shouldn't be any funny business where some invocations do multiple things at once. Therefore, this helped me structure CB by assuming that every time it runs, it'll perform only one distinct action, and I can build everything else around that assumption. 9 | 10 | 2. Next, I had to decide what language to write CB in. I already knew C++ from Hajime, one of my earlier projects. And I've been learning it since I was 8! Plus, it's super fast and filled with tons of fun features starting with the C++17 standard. So, C++ it was! 11 | 12 | 3. After deciding on the modus operandi and programming language, I made a super basic version of CB. I actually wrote this initial version in Bash. That was due to me wanting to see if such a task could be done in a "simpler" language before moving to the big guns of C++. Unfortunately, it didn't 13 | turn out so well. The Bash version was filled with redundant code and was hard to work on. Due to me not wanting to suffer any further, I rewrote the Bash version in C++. 14 | 15 | 4. I started adding more and more features after sharing my CB project online and then receiving valuable feedback. I also researched other, similar projects like CopyQ, Maccy, Xclip, and wl-clipboard, and incorporating their features in a way that would suit the CB philosophy best. 16 | 17 | 5. From there, it's been smooth sailing and in fact a little boring because I additionally incorporated automated code formatting, a contribution from another fellow developer, integration tests, and a coherent design language. The tests have kept bugs and regressions to a minimum. The code formatting keeps everything looking tidy. And, the design language makes CB one 18 | of the most beautiful tools to use on the command line. 19 | -------------------------------------------------------------------------------- /app.getclipboard.Clipboard.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Clipboard 3 | Icon=app.getclipboard.Clipboard 4 | GenericName=Clipboard Manager 5 | Exec=bash -c "export CLIPBOARD_SILENT=1; while true; do cb hs; CLIPBOARD_NOGUI=1 cb; echo -n -e '\033[?25l'; sleep 2; clear; done" 6 | Type=Application 7 | Terminal=true 8 | Categories=Utility;Office;Development 9 | Comment=Cut, copy, and paste anything, anytime, anywhere 10 | -------------------------------------------------------------------------------- /app.getclipboard.Clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/app.getclipboard.Clipboard.png -------------------------------------------------------------------------------- /app.getclipboard.Clipboard.yml: -------------------------------------------------------------------------------- 1 | app-id: app.getclipboard.Clipboard 2 | runtime: org.freedesktop.Platform 3 | runtime-version: '22.08' 4 | sdk: org.freedesktop.Sdk 5 | command: cb 6 | finish-args: 7 | - --share=ipc 8 | - --socket=fallback-x11 9 | - --socket=wayland 10 | - --filesystem=host 11 | - --filesystem=xdg-run/Clipboard 12 | - --socket=pulseaudio 13 | modules: 14 | - name: cb 15 | buildsystem: cmake-ninja 16 | post-install: 17 | - install -D app.getclipboard.Clipboard.metainfo.xml /app/share/metainfo/app.getclipboard.Clipboard.metainfo.xml 18 | - install -D app.getclipboard.Clipboard.desktop /app/share/applications/app.getclipboard.Clipboard.desktop 19 | - install -D app.getclipboard.Clipboard.png /app/share/icons/hicolor/512x512/apps/app.getclipboard.Clipboard.png 20 | sources: 21 | - type: git 22 | url: https://github.com/Slackadays/Clipboard 23 | branch: main 24 | - type: file 25 | path: app.getclipboard.Clipboard.metainfo.xml 26 | - type: file 27 | path: app.getclipboard.Clipboard.desktop 28 | - type: file 29 | path: app.getclipboard.Clipboard.png 30 | config-opts: ["-DCMAKE_BUILD_TYPE=Release"] -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | /.vscode/* 3 | *idea* 4 | settings.json 5 | dummy/ 6 | !.gitignore -------------------------------------------------------------------------------- /documentation/completions/cb.bash: -------------------------------------------------------------------------------- 1 | #/usr/bin/env bash 2 | complete_cb() { 3 | if [ "${#COMP_WORDS[@]}" == "2" ]; then 4 | COMPREPLY=($(compgen -W "cut copy paste clear show edit add remove note swap status info load import export history ignore search config help" ${COMP_WORDS[1]})) 5 | return 6 | fi 7 | if [ "${COMP_WORDS[1]}" == "cut" ] || [ "${COMP_WORDS[1]}" == "ct" ] || [ "${COMP_WORDS[1]}" == "copy" ] || [ "${COMP_WORDS[1]}" == "cp" ] || [ "${COMP_WORDS[1]}" == "add" ] || [ "${COMP_WORDS[1]}" == "ad" ]; then 8 | COMPREPLY=($(compgen -A file ${COMP_WORDS[COMP_CWORD]})) 9 | return 10 | fi 11 | } 12 | 13 | complete -F complete_cb cb -------------------------------------------------------------------------------- /documentation/completions/cb.fish: -------------------------------------------------------------------------------- 1 | set -l commands cut copy paste clear show edit add remove note swap status info load import export history ignore search config help 2 | 3 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a cut -d 'cut something' 4 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a copy -d 'copy something' 5 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a paste -d 'paste something' 6 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a clear -d 'clear clipboard' 7 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a show -d 'show clipboard content' 8 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a edit -d 'edit clipboard content' 9 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a add -d 'add something to clipboard' 10 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a remove -d 'remove something from clipboard' 11 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a note -d 'add note to clipboard' 12 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a swap -d 'swap clipboard content' 13 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a status -d 'show status' 14 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a info -d 'show clipboard info' 15 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a load -d 'load clipboard into other clipboard' 16 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a import -d 'import clipboard from file' 17 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a export -d 'export clipboard to file' 18 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a history -d 'show clipboard history' 19 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a ignore -d 'ignore content' 20 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a search -d 'search clipboard content' 21 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a config -d 'show CB config' 22 | complete -c cb -f -n "not __fish_seen_subcommand_from $commands" -a help -d 'show help for CB' -------------------------------------------------------------------------------- /documentation/completions/cb.zsh: -------------------------------------------------------------------------------- 1 | #compdef cb 2 | local -a actions 3 | actions=( 4 | "cut:cut something" 5 | "copy:copy something" 6 | "paste:paste something" 7 | "clear:clear clipboard" 8 | "show:show clipboard content" 9 | "edit:edit clipboard content" 10 | "add:add something to clipboard" 11 | "remove:remove something from clipboard" 12 | "note:add note to clipboard" 13 | "swap:swap clipboard content" 14 | "status:show status" 15 | "info:show clipboard info" 16 | "load:load clipboard into other clipboard" 17 | "import:import clipboard from file" 18 | "export:export clipboard to file" 19 | "history:show clipboard history" 20 | "ignore:ignore content" 21 | "search:search clipboard content" 22 | "config:show CB config" 23 | "help:show help for CB" 24 | ) 25 | # only put up to one action in front of the cb command 26 | if [ "${#words[@]}" -eq 2 ]; then 27 | _describe 'command' actions 28 | return 29 | fi 30 | # now complete files 31 | if [ "${words[2]}" = "cut" ] || [ "${words[2]}" = "ct" ] || [ "${words[2]}" = "copy" ] || [ "${words[2]}" = "cp" ] || [ "${words[2]}" = "add" ] || [ "${words[2]}" = "ad" ]; then 32 | _files 33 | return 34 | fi -------------------------------------------------------------------------------- /documentation/fonts/lobster_two/LobsterTwo-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/lobster_two/LobsterTwo-Bold.ttf -------------------------------------------------------------------------------- /documentation/fonts/lobster_two/LobsterTwo-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/lobster_two/LobsterTwo-BoldItalic.ttf -------------------------------------------------------------------------------- /documentation/fonts/lobster_two/LobsterTwo-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/lobster_two/LobsterTwo-Italic.ttf -------------------------------------------------------------------------------- /documentation/fonts/lobster_two/LobsterTwo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/lobster_two/LobsterTwo-Regular.ttf -------------------------------------------------------------------------------- /documentation/fonts/permanent_marker/PermanentMarker-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/permanent_marker/PermanentMarker-Regular.ttf -------------------------------------------------------------------------------- /documentation/fonts/pt_sans/PTSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/pt_sans/PTSans-Bold.ttf -------------------------------------------------------------------------------- /documentation/fonts/pt_sans/PTSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/fonts/pt_sans/PTSans-Regular.ttf -------------------------------------------------------------------------------- /documentation/readme-assets/AllExceptWindows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/AllExceptWindows.png -------------------------------------------------------------------------------- /documentation/readme-assets/CB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CB.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBBanner.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBBannerGitHub.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBBannerGitHub.jpg -------------------------------------------------------------------------------- /documentation/readme-assets/CBDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBDemo.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBHowToUse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBHowToUse.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBHowToUse.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBHowToUse.xcf -------------------------------------------------------------------------------- /documentation/readme-assets/CBQuickInstallation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBQuickInstallation.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBQuickInstallation.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBQuickInstallation.xcf -------------------------------------------------------------------------------- /documentation/readme-assets/CBSimpleConfiguration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBSimpleConfiguration.png -------------------------------------------------------------------------------- /documentation/readme-assets/CBSimpleConfiguration.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBSimpleConfiguration.xcf -------------------------------------------------------------------------------- /documentation/readme-assets/CBThemes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CBThemes.png -------------------------------------------------------------------------------- /documentation/readme-assets/ClipboardDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/ClipboardDemo.gif -------------------------------------------------------------------------------- /documentation/readme-assets/ClipboardMakesYourLifeEasy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/ClipboardMakesYourLifeEasy.png -------------------------------------------------------------------------------- /documentation/readme-assets/CustomizeClipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/CustomizeClipboard.png -------------------------------------------------------------------------------- /documentation/readme-assets/EnvironmentVariables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/EnvironmentVariables.png -------------------------------------------------------------------------------- /documentation/readme-assets/Examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/Examples.png -------------------------------------------------------------------------------- /documentation/readme-assets/Features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/Features.png -------------------------------------------------------------------------------- /documentation/readme-assets/Flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/Flags.png -------------------------------------------------------------------------------- /documentation/readme-assets/GetItOnGitHub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/GetItOnGitHub.png -------------------------------------------------------------------------------- /documentation/readme-assets/GetStartedBelow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/GetStartedBelow.png -------------------------------------------------------------------------------- /documentation/readme-assets/HowToUsePrompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/HowToUsePrompt.png -------------------------------------------------------------------------------- /documentation/readme-assets/InstallManually.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/InstallManually.png -------------------------------------------------------------------------------- /documentation/readme-assets/MoveThingsAround.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/MoveThingsAround.png -------------------------------------------------------------------------------- /documentation/readme-assets/NeedHelp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/NeedHelp.png -------------------------------------------------------------------------------- /documentation/readme-assets/NeedHelp.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/NeedHelp.xcf -------------------------------------------------------------------------------- /documentation/readme-assets/PremadeBuilds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/PremadeBuilds.png -------------------------------------------------------------------------------- /documentation/readme-assets/ProductivityTools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/ProductivityTools.png -------------------------------------------------------------------------------- /documentation/readme-assets/ProductivityTools.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 42 | 44 | 49 | You now have a second brain. 63 | 64 | 65 | -------------------------------------------------------------------------------- /documentation/readme-assets/SeeEverything.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/SeeEverything.png -------------------------------------------------------------------------------- /documentation/readme-assets/ThankYou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/ThankYou.png -------------------------------------------------------------------------------- /documentation/readme-assets/ThankYou.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/ThankYou.xcf -------------------------------------------------------------------------------- /documentation/readme-assets/TheBasics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/TheBasics.png -------------------------------------------------------------------------------- /documentation/readme-assets/TipsAndTricks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/TipsAndTricks.png -------------------------------------------------------------------------------- /documentation/readme-assets/Uninstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/Uninstall.png -------------------------------------------------------------------------------- /documentation/readme-assets/WindowsRunAsAdmin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/readme-assets/WindowsRunAsAdmin.png -------------------------------------------------------------------------------- /documentation/readme-assets/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /documentation/readme-assets/eyecandy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 40 | 42 | 45 | 49 | 53 | 54 | 63 | 64 | 69 | eye candy 80 | 81 | 82 | -------------------------------------------------------------------------------- /documentation/website/config.toml: -------------------------------------------------------------------------------- 1 | # The URL the site will be built for 2 | base_url = "https://getclipboard.app" 3 | 4 | title = "The Clipboard Project - Homepage" 5 | 6 | theme = "juice" 7 | 8 | # Whether to automatically compile all Sass files in the sass directory 9 | compile_sass = true 10 | 11 | # Whether to build a search index to be used later on by a JavaScript library 12 | build_search_index = false 13 | 14 | [markdown] 15 | # Whether to do syntax highlighting 16 | # Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola 17 | highlight_code = true 18 | highlight_theme = "inspired-github" 19 | 20 | render_emoji = true 21 | 22 | [extra] 23 | # Put all your custom variables here 24 | juice_logo_name = "The Clipboard Project" 25 | juice_logo_path = "cb_small.png" 26 | juice_extra_menu = [ 27 | { title = "Discord", link = "https://discord.gg/jc7bcEeR" }, 28 | { title = "Star us on GitHub", link = "https://github.com/Slackadays/Clipboard" } 29 | ] 30 | repository_url = "https://github.com/Slackadays/Clipboard" 31 | -------------------------------------------------------------------------------- /documentation/website/static/.well-known/org.flathub.VerifiedApps.txt: -------------------------------------------------------------------------------- 1 | 3907d38c-1835-40e5-8e39-54f3966e020b -------------------------------------------------------------------------------- /documentation/website/static/CBBannerGitHub.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/CBBannerGitHub.jpg -------------------------------------------------------------------------------- /documentation/website/static/ClipboardDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/ClipboardDemo.gif -------------------------------------------------------------------------------- /documentation/website/static/LiveTerminalDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/LiveTerminalDemo.png -------------------------------------------------------------------------------- /documentation/website/static/LobsterTwo-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/LobsterTwo-Bold.ttf -------------------------------------------------------------------------------- /documentation/website/static/LobsterTwo-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/LobsterTwo-BoldItalic.ttf -------------------------------------------------------------------------------- /documentation/website/static/cb_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/cb_small.png -------------------------------------------------------------------------------- /documentation/website/static/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/demo.png -------------------------------------------------------------------------------- /documentation/website/static/get_it_on_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/static/get_it_on_github.png -------------------------------------------------------------------------------- /documentation/website/templates/page.html: -------------------------------------------------------------------------------- 1 | {% import "_macros.html" as macros %} 2 | {% extends "index.html" %} 3 | 4 | {% block title %}{{ page.title }} | {{ super() }} {% endblock title %} 5 | 6 | {% block header %} 7 |
8 | {{ macros::render_header() }} 9 |
10 | 37 | {% endblock header %} 38 | 39 | {% block content %} 40 |
{{ page.description }}
41 | {{ page.content | safe }} 42 | {% endblock content %} 43 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | public 4 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Huhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/config.toml: -------------------------------------------------------------------------------- 1 | # The URL the site will be built for 2 | base_url = "/" 3 | 4 | title = "Juice - An intuitive, elegant, and lightweight Zola theme for product sites." 5 | # default_language = "en" 6 | 7 | # Whether to automatically compile all Sass files in the sass directory 8 | compile_sass = true 9 | 10 | # Whether to build a search index to be used later on by a JavaScript library 11 | build_search_index = false 12 | 13 | # Configuration of the Markdown rendering 14 | [markdown] 15 | # Whether to do syntax highlighting 16 | # Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola 17 | highlight_code = true 18 | highlight_theme = "inspired-github" 19 | 20 | [extra] 21 | juice_logo_name = "Juice" 22 | juice_logo_path = "juice.svg" 23 | juice_extra_menu = [ 24 | { title = "Github", link = "https://github.com/huhu/juice" } 25 | ] 26 | # Add page titles here to exclude them from the nav section (case sensitive) 27 | juice_exclude_menu = [ 28 | "exclude_from_nav" 29 | ] 30 | repository_url = "https://github.com/huhu/juice" 31 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/content/about.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "About" 3 | description = "About" 4 | weight = 3 5 | +++ 6 | 7 | # Juice 8 | 9 | **Juice** is an intuitive, elegant, and responsive Zola theme for product sites. 10 | Built by [Huhu.io](https://huhu.io), adopted by a several product sites. 11 | 12 | # Logo 13 | 14 | ![](/juice.svg) 15 | 16 | # Zola 17 | 18 | [Zola](https://www.getzola.org) is a fast static site generator in a single binary with everything built-in. 19 | 20 | 21 | # Huhu.io 22 | 23 | [Huhu.io](https://huhu.io) is a global community of coders dedicated to making cool stuff coders need and want. 24 | We focus on enabling the developer community by curating, incubating, and launching tools based on great ideas, 25 | providing support and funding that allows our engineers to develop what they want, the way they want. 26 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/content/changelog.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Changelog" 3 | description = "Changelog" 4 | weight = 2 5 | +++ 6 | 7 | # v0.6.0 - 2021-10-05 8 | 9 | - Add `favicon` block. 10 | - Always align footer bottom. {{ issue(id=4) }} 11 | - Support config favicon. Fixes {{ issue(id=5) }}. 12 | - Table of Content supports auto-scroll if the list is too long. 13 | 14 | # v0.5.0 - 2021-03-02 15 | 16 | - Add `issue` shortcode. 17 | - Add `sidebar` block. 18 | - Adjust blockquote background color. 19 | - Fix explore-more class left align. 20 | 21 | # v0.4.0 - 2020-11-18 22 | 23 | - Prevent showcase images be included by downstream Zola project. 24 | - Fix TOC highlight in localhost mode. See {{ issue(id=1) }}. 25 | - Hide TOC for empty markdown content page. 26 | 27 | # v0.3.0 - 2020-07-17 28 | 29 | - Rename css filename to avoid conflicts. 30 | - Replace sass variables with css variable. 31 | - Add `--toc-highlight-text-color` variable. 32 | - Add normalize.css. 33 | 34 | # v0.2.0 - 2020-06-28 35 | 36 | - Add extra juice_extra_menu config. 37 | - Add color customization CSS variables. 38 | - Improve docs and blockquote style. 39 | - Support customize logo and name. 40 | 41 | # v0.1.0 - 2020-06-21 42 | 43 | - First release! -------------------------------------------------------------------------------- /documentation/website/themes/juice/content/exclude_from_nav.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "exclude_from_nav" 3 | description = "Page without nav link" 4 | weight = 3 5 | +++ 6 | 7 | # Hidden page 8 | 9 | This page will not be added to the nav links in the header. 10 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/content/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/themes/juice/content/favicon.ico -------------------------------------------------------------------------------- /documentation/website/themes/juice/content/showcases.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Showcases" 3 | description = "Showcases" 4 | weight = 1 5 | +++ 6 | 7 | # Pull request 8 | 9 | If you use **Juice** as your theme, feel free to make Pull request. 10 | 11 | Here are some steps to help you get started: 12 | 13 | - Change the [content/showcases.md](https://github.com/huhu/juice/blob/master/content/showcases.md) file, add your product site. Make sure the lexicographical order. 14 | - Add a link to your product site. 15 | 16 | # Gallery 17 | 18 | Here are some product websites which use **Juice** as the theme. 19 | Sort by lexicographical order. For more showcases, please visit [here](https://github.com/search?l=&p=1&q=theme+%3D+%22juice%22+filename%3Aconfig.toml&ref=advsearch&type=Code). 20 | 21 | ## Acton Lang 22 | 23 | [https://www.acton-lang.org/](https://www.acton-lang.org/) 24 | 25 | ## Arara 26 | 27 | [https://islandoftex.gitlab.io/arara/](https://islandoftex.gitlab.io/arara/) 28 | 29 | ## Angular Rust 30 | 31 | [https://angular-rust.github.io/](https://angular-rust.github.io/) 32 | 33 | ## Atlas Language 34 | 35 | [https://atlas-language.github.io/](https://atlas-language.github.io/) 36 | 37 | ## Avatar CLI 38 | 39 | [https://avatar-cli.dev/](https://avatar-cli.dev/) 40 | 41 | ## C/C++ Search Extension 42 | 43 | [https://cpp.extension.sh/](https://cpp.extension.sh/) 44 | 45 | ## Crow Translate 46 | 47 | [https://crow-translate.github.io/](https://crow-translate.github.io/) 48 | 49 | ## Drogue IOT 50 | 51 | [https://www.drogue.io/](https://www.drogue.io/) 52 | 53 | ## El Monitorro 54 | 55 | [https://elmonitorro.badykov.com/](https://elmonitorro.badykov.com/) 56 | 57 | ## Erg Lang 58 | 59 | [https://erg-lang.org/](https://erg-lang.org/) 60 | 61 | ## Godot-rust 62 | 63 | [https://godot-rust.github.io/](https://godot-rust.github.io/) 64 | 65 | ## GoToFix (JP) 66 | 67 | [https://gotofix.kumassy.com/](https://gotofix.kumassy.com/) 68 | 69 | ## Go Search Extension 70 | 71 | [https://go.extension.sh/](https://go.extension.sh/) 72 | 73 | ## Gradecoin 74 | 75 | [https://gradecoin.xyz/](https://gradecoin.xyz/) 76 | 77 | ## Insta.rs 78 | 79 | [https://insta.rs/](https://insta.rs/) 80 | 81 | ## Instant markdown 82 | 83 | [https://instant-markdown.github.io/](https://instant-markdown.github.io/) 84 | 85 | ## ImpftHessen (DE) 86 | 87 | [https://impft-hessen.de/](https://impft-hessen.de/) 88 | 89 | ## JS Search Extension 90 | 91 | [https://js.extension.sh/](https://js.extension.sh/) 92 | 93 | ## Fun Notation 94 | 95 | [https://www.notation.fun/](https://www.notation.fun/) 96 | 97 | ## PeopleForBike 98 | 99 | [https://peopleforbikes.github.io/](https://peopleforbikes.github.io/) 100 | 101 | ## Rust Search Extension 102 | 103 | [https://rust.extension.sh/](https://rust.extension.sh/) 104 | 105 | ## Stitcherd 106 | 107 | [https://stitcherd.vhodges.dev/](https://stitcherd.vhodges.dev/) 108 | 109 | ## Streamson 110 | 111 | [https://streamson.henek.name/](https://streamson.henek.name/) 112 | 113 | ## Tokay lang 114 | 115 | [https://tokay.dev](https://tokay.dev) 116 | 117 | ## Trunk 118 | 119 | [https://trunkrs.dev/](https://trunkrs.dev/) 120 | 121 | ## Vidar 122 | 123 | [https://calebsacks.me/vidar/](https://calebsacks.me/vidar/) 124 | 125 | ## zDevelopers 126 | 127 | [https://dev.zcraft.fr/](https://dev.zcraft.fr/) -------------------------------------------------------------------------------- /documentation/website/themes/juice/sass/_markdown.scss: -------------------------------------------------------------------------------- 1 | .content { 2 | padding: 0 40px; 3 | display: flex; 4 | flex-direction: column; 5 | overflow-x: auto; 6 | } 7 | 8 | .content pre { 9 | overflow-x: auto; 10 | padding: 1.25em 1.5em; 11 | white-space: pre; 12 | word-wrap: normal; 13 | background-color: var(--code-background-color); 14 | color: var(--code-color); 15 | font-size: .875em; 16 | font-family: monospace; 17 | } 18 | 19 | .content code { 20 | background-color: var(--code-background-color); 21 | color: var(--code-color); 22 | font-size: .875em; 23 | font-weight: normal; 24 | padding: 0.25em 0.5em; 25 | font-family: monospace; 26 | } 27 | 28 | .content pre code { 29 | padding: 0; 30 | } 31 | 32 | .content a { 33 | color: var(--primary-link-color); 34 | 35 | &:hover { 36 | text-decoration: underline; 37 | } 38 | } 39 | 40 | .content blockquote { 41 | border-left: #e2dede 8px solid; 42 | margin: 0; 43 | background-color: #f2f1f0; 44 | padding: 0 20px; 45 | } 46 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/sass/_text.scss: -------------------------------------------------------------------------------- 1 | .heading-text { 2 | font-family: var(--header-font-family); 3 | font-size: 32px; 4 | font-weight: 600; 5 | padding: 10px 0 25px 0; 6 | color: var(--primary-text-color); 7 | } 8 | 9 | h1, .title-text { 10 | font-family: var(--header-font-family); 11 | font-size: 25px; 12 | font-weight: 500; 13 | color: var(--primary-text-color); 14 | border-left: var(--primary-color) 8px solid; 15 | padding-left: 10px; 16 | } 17 | 18 | h2, .subtitle-text { 19 | font-family: var(--header-font-family); 20 | font-size: 20px; 21 | font-weight: 500; 22 | color: var(--primary-text-color); 23 | } 24 | 25 | .text { 26 | font-family: var(--text-font-family); 27 | font-size: 18px; 28 | font-weight: 400; 29 | line-height: 26px; 30 | letter-spacing: 0.2px; 31 | color: var(--primary-text-color); 32 | } 33 | 34 | .subtext { 35 | font-family: var(--text-font-family); 36 | font-size: 16px; 37 | font-weight: 400; 38 | letter-spacing: 0.1px; 39 | } -------------------------------------------------------------------------------- /documentation/website/themes/juice/sass/_ultility.scss: -------------------------------------------------------------------------------- 1 | .text-center { 2 | text-align: center; 3 | } 4 | 5 | .pos-absolute { 6 | right: 0; 7 | left: 0; 8 | position: absolute; 9 | } 10 | 11 | .box-shadow { 12 | box-shadow: 0 2px 10px 2px var(--shadow-color); 13 | } -------------------------------------------------------------------------------- /documentation/website/themes/juice/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/documentation/website/themes/juice/screenshot.png -------------------------------------------------------------------------------- /documentation/website/themes/juice/templates/_macros.html: -------------------------------------------------------------------------------- 1 | {% macro render_header() %} 2 | {% set section = get_section(path="_index.md") %} 3 | 4 | 8 | 9 | 10 | 23 | {% endmacro render_header %} 24 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/templates/_variables.html: -------------------------------------------------------------------------------- 1 | 46 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/templates/page.html: -------------------------------------------------------------------------------- 1 | {% import "_macros.html" as macros %} 2 | {% extends "index.html" %} 3 | 4 | {% block title %}{{ page.title }} | {{ super() }} {% endblock title %} 5 | 6 | {% block header %} 7 |
8 | {{ macros::render_header() }} 9 |
10 | {% endblock header %} 11 | 12 | {% block content %} 13 |
{{ page.description }}
14 | {{ page.content | safe }} 15 | {% endblock content %} -------------------------------------------------------------------------------- /documentation/website/themes/juice/templates/shortcodes/issue.html: -------------------------------------------------------------------------------- 1 | #{{ id }} -------------------------------------------------------------------------------- /documentation/website/themes/juice/theme.toml: -------------------------------------------------------------------------------- 1 | name = "juice" 2 | description = "An intuitive, elegant, and lightweight Zola theme for product sites." 3 | license = "MIT" 4 | homepage = "https://github.com/huhu/juice" 5 | min_version = "0.11.0" 6 | demo = "https://juice.huhu.io" 7 | 8 | [extra] 9 | 10 | [author] 11 | name = "Huhu teams" 12 | homepage = "https://huhu.io" 13 | -------------------------------------------------------------------------------- /documentation/website/themes/juice/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "silent": true 4 | } 5 | } -------------------------------------------------------------------------------- /install.ps1: -------------------------------------------------------------------------------- 1 | if (Test-Path $env:USERPROFILE\scoop) { 2 | scoop install clipboard 3 | exit 4 | } 5 | 6 | Invoke-WebRequest https://github.com/Slackadays/Clipboard/releases/latest/download/clipboard-windows-amd64.zip -OutFile clipboard-windows-amd64.zip 7 | Expand-Archive clipboard-windows-amd64.zip -DestinationPath .\clipboard-windows-amd64 8 | 9 | New-Item -ItemType Directory -Force -Path "C:\Program Files\Clipboard" 10 | 11 | Copy-Item .\clipboard-windows-amd64\bin\cb.exe -Force -Destination "C:\Program Files\Clipboard\cb.exe" 12 | 13 | $Old = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name path).path 14 | $New = "$Old;C:\Program Files\Clipboard" 15 | Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name path -Value $New 16 | 17 | Remove-Item .\clipboard-windows-amd64.zip -Force 18 | Remove-Item .\clipboard-windows-amd64 -Force -Recurse 19 | 20 | Write-Host "Please restart to use CB" 21 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | default: 2 | @just --list 3 | 4 | build: 5 | if [ ! -d "build" ]; then mkdir build; fi 6 | 7 | cd build; cmake .. -DCMAKE_BUILD_TYPE=Release 8 | 9 | cd build; cmake --build . -j 12 10 | 11 | cd build; sudo cmake --install . 12 | 13 | clean: 14 | if [ -d "build" ]; then rm -rf build; fi -------------------------------------------------------------------------------- /snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: clipboard 2 | version: "0.10.1" 3 | summary: The ultimate clipboard manager for the terminal 4 | description: | 5 | The Clipboard Project is one of the most advanced clipboard managers ever. 6 | Cut, copy, and paste anything, anytime, anywhere with unlimited capacity, clipboards, and history. 7 | It's feature packed and easy to use by anybody. 8 | confinement: strict 9 | base: core22 10 | parts: 11 | clipboard: 12 | plugin: cmake 13 | cmake-parameters: 14 | - -DCMAKE_BUILD_TYPE=Release 15 | - -DCMAKE_INSTALL_LIBDIR=bin 16 | source-type: git 17 | source: https://github.com/Slackadays/Clipboard 18 | source-branch: main 19 | build-packages: 20 | - g++ 21 | - make 22 | - cmake 23 | - libasound2-dev 24 | - liburing-dev 25 | - libx11-dev 26 | - libwayland-dev 27 | - wayland-protocols 28 | - libssl-dev 29 | stage-packages: 30 | - libasound2-dev 31 | - liburing-dev 32 | - libx11-dev 33 | - libwayland-dev 34 | apps: 35 | clipboard: 36 | command: usr/local/bin/cb 37 | plugs: 38 | - alsa 39 | - x11 40 | - wayland 41 | - home 42 | - removable-media -------------------------------------------------------------------------------- /src/cb/src/actions/add.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void addFiles() { 21 | if (path.holdsRawDataInCurrentEntry()) 22 | error_exit( 23 | "%s", 24 | formatColors("[error][inverse] ✘ [noinverse] You can't add items to text. [blank][help] ⬤ Try copying text first, or add " 25 | "text instead.[blank]\n") 26 | ); 27 | for (const auto& f : copying.items) 28 | copyItem(f); 29 | } 30 | 31 | void addData() { 32 | if (path.holdsRawDataInCurrentEntry()) { 33 | std::string content; 34 | if (io_type == IOType::Pipe) 35 | content = pipedInContent(); 36 | else 37 | for (size_t i = 0; i < copying.items.size(); i++) { 38 | content += copying.items.at(i).string(); 39 | if (i != copying.items.size() - 1) content += " "; 40 | } 41 | successes.bytes += writeToFile(path.data.raw, content, true); 42 | } else if (!fs::is_empty(path.data)) { 43 | error_exit( 44 | "%s", 45 | formatColors("[error][inverse] ✘ [noinverse] You can't add text to items. [blank][help] ⬤ Try copying text first, or add a " 46 | "file instead.[blank]\n") 47 | ); 48 | } else { 49 | if (io_type == IOType::Pipe) 50 | pipeIn(); 51 | else if (io_type == IOType::Text) 52 | for (size_t i = 0; i < copying.items.size(); i++) { 53 | successes.bytes += writeToFile(path.data.raw, copying.items.at(i).string()); 54 | if (i != copying.items.size() - 1) successes.bytes += writeToFile(path.data.raw, " "); 55 | } 56 | } 57 | } 58 | 59 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/copy.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void copyItem(const fs::path& f, const bool use_regular_copy) { 21 | auto actuallyCopyItem = [&] { 22 | if (fs::is_directory(f)) { 23 | auto target = f.filename().empty() ? f.parent_path().filename() : f.filename(); 24 | fs::create_directories(path.data / target); 25 | fs::copy(f, path.data / target, copying.opts); 26 | } else { 27 | fs::copy(f, path.data / f.filename(), use_regular_copy ? copying.opts : copying.opts | fs::copy_options::create_hard_links); 28 | } 29 | incrementSuccessesForItem(f); 30 | if (action == Action::Cut) writeToFile(path.metadata.originals, fs::absolute(f).string() + "\n", true); 31 | }; 32 | try { 33 | actuallyCopyItem(); 34 | } catch (const fs::filesystem_error& e) { 35 | if (!use_regular_copy && e.code() == std::errc::cross_device_link) { 36 | copyItem(f, true); 37 | } else { 38 | copying.failedItems.emplace_back(f.string(), e.code()); 39 | } 40 | } 41 | } 42 | 43 | void copy() { 44 | for (const auto& f : copying.items) 45 | copyItem(f); 46 | } 47 | 48 | void copyText() { 49 | for (size_t i = 0; i < copying.items.size(); i++) { 50 | copying.buffer += copying.items.at(i).string(); 51 | if (i != copying.items.size() - 1) copying.buffer += " "; 52 | } 53 | writeToFile(path.data.raw, copying.buffer); 54 | 55 | if (!output_silent && !confirmation_silent) { 56 | stopIndicator(); 57 | printf(formatColors("[success][inverse] ✔ [noinverse] %s text \"[bold]%s[blank][success]\"[blank]\n").data(), did_action[action].data(), copying.buffer.data()); 58 | } 59 | 60 | if (action == Action::Cut) writeToFile(path.metadata.originals, path.data.raw.string()); 61 | successes.bytes = 0; // temporarily disable the bytes success message 62 | } 63 | 64 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/edit.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | #include 18 | 19 | namespace PerformAction { 20 | 21 | void edit() { 22 | if (!path.holdsRawDataInCurrentEntry()) { 23 | if (path.holdsDataInCurrentEntry()) 24 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] You can currently only edit text content. [help]⬤ Try copying some text instead.[blank]\n")); 25 | else 26 | std::ofstream temp(path.data.raw); 27 | } 28 | 29 | auto editor = findUsableEditor(); 30 | 31 | if (!editor) error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] CB couldn't find a suitable editor to use. [help]⬤ Try setting the CLIPBOARD_EDITOR environment variable.[blank]\n")); 32 | 33 | // now run this editor with the text file as the argument 34 | auto command = editor.value() + " " + path.data.raw.string(); 35 | 36 | stopIndicator(); 37 | 38 | int res = system(command.data()); 39 | 40 | if (res != 0) error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] CB couldn't open the editor. [help]⬤ Try setting the CLIPBOARD_EDITOR environment variable.[blank]\n")); 41 | } 42 | 43 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/export.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void exportClipboards() { 21 | std::vector destinations; 22 | if (!copying.items.empty()) 23 | std::transform(copying.items.begin(), copying.items.end(), std::back_inserter(destinations), [](const auto& item) { return item.string(); }); 24 | else { 25 | for (const auto& entry : fs::directory_iterator(global_path.temporary)) 26 | destinations.emplace_back(entry.path().filename().string()); 27 | for (const auto& entry : fs::directory_iterator(global_path.persistent)) 28 | destinations.emplace_back(entry.path().filename().string()); 29 | } 30 | 31 | fs::path exportDirectory(fs::current_path() / "Exported_Clipboards"); 32 | 33 | try { 34 | if (fs::exists(exportDirectory)) fs::remove_all(exportDirectory); 35 | fs::create_directory(exportDirectory); 36 | } catch (const fs::filesystem_error& e) { 37 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] CB couldn't create the export directory. [help]⬤ Try checking if you have the right permissions or not.[blank]\n")); 38 | } 39 | 40 | auto exportClipboard = [&](const std::string& name) { 41 | try { 42 | Clipboard clipboard(name); 43 | clipboard.getLock(); 44 | if (clipboard.isUnused()) return; 45 | fs::copy(clipboard, exportDirectory / name, copying.opts); 46 | fs::remove(exportDirectory / name / constants.metadata_directory / constants.lock_name); 47 | clipboard.releaseLock(); 48 | successes.clipboards++; 49 | } catch (const fs::filesystem_error& e) { 50 | copying.failedItems.emplace_back(name, e.code()); 51 | } 52 | }; 53 | 54 | for (const auto& name : destinations) 55 | exportClipboard(name); 56 | 57 | if (destinations.empty() || successes.clipboards == 0) { 58 | stopIndicator(); 59 | fprintf(stderr, "%s", no_clipboard_contents_message().data()); 60 | error_exit(clipboard_action_prompt(), clipboard_invocation, clipboard_invocation); 61 | } 62 | } 63 | 64 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/help.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/cb/src/actions/help.cpp -------------------------------------------------------------------------------- /src/cb/src/actions/import.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void importClipboards() { 21 | fs::path importDirectory; 22 | if (copying.items.empty()) 23 | importDirectory = fs::current_path() / "Exported_Clipboards"; 24 | else 25 | importDirectory = copying.items.at(0); 26 | 27 | if (!fs::exists(importDirectory)) 28 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] The directory you're trying to import from doesn't exist. [help]⬤ Try choosing a different one instead.[blank]\n")); 29 | 30 | if (!fs::is_directory(importDirectory)) 31 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] The directory you're trying to import from isn't a directory. [help]⬤ Try choosing a different one instead.[blank]\n")); 32 | 33 | for (const auto& entry : fs::directory_iterator(importDirectory)) { 34 | if (!entry.is_directory()) 35 | copying.failedItems.emplace_back(entry.path().filename().string(), std::make_error_code(std::errc::not_a_directory)); 36 | else { 37 | try { 38 | auto target = (isPersistent(entry.path().filename().string()) ? global_path.persistent : global_path.temporary) / entry.path().filename(); 39 | if (fs::exists(target)) { 40 | using enum CopyPolicy; 41 | switch (copying.policy) { 42 | case SkipAll: 43 | continue; 44 | case ReplaceAll: 45 | fs::copy(entry.path(), target, fs::copy_options::recursive | fs::copy_options::overwrite_existing); 46 | successes.clipboards++; 47 | break; 48 | default: 49 | stopIndicator(); 50 | copying.policy = userDecision(entry.path().filename().string()); 51 | startIndicator(); 52 | if (copying.policy == ReplaceOnce || copying.policy == ReplaceAll) { 53 | fs::copy(entry.path(), target, fs::copy_options::recursive | fs::copy_options::overwrite_existing); 54 | successes.clipboards++; 55 | } 56 | break; 57 | } 58 | } else { 59 | fs::copy(entry.path(), target, fs::copy_options::recursive); 60 | successes.clipboards++; 61 | } 62 | } catch (const fs::filesystem_error& e) { 63 | copying.failedItems.emplace_back(entry.path().filename().string(), e.code()); 64 | } 65 | } 66 | } 67 | } 68 | 69 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/load.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void load() { 21 | if (!path.holdsDataInCurrentEntry()) { 22 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] The clipboard you're trying to load from is empty. [help]⬤ Try choosing a different source instead.[blank]\n")); 23 | } 24 | 25 | std::vector destinations; 26 | if (!copying.items.empty()) 27 | std::transform(copying.items.begin(), copying.items.end(), std::back_inserter(destinations), [](const auto& item) { return item.string(); }); 28 | else 29 | destinations.emplace_back(constants.default_clipboard_name); 30 | 31 | if (std::find(destinations.begin(), destinations.end(), clipboard_name) != destinations.end()) 32 | error_exit( 33 | "%s", 34 | formatColors("[error][inverse] ✘ [noinverse] You can't load a clipboard into itself. [help]⬤ Try choosing a different source instead, or choose different destinations.[blank]\n") 35 | ); 36 | 37 | for (const auto& destination_number : destinations) { 38 | Clipboard destination(destination_number); 39 | try { 40 | for (const auto& entry : fs::directory_iterator(path.data)) { 41 | auto target = destination.data / entry.path().filename(); 42 | auto loadItem = [&](bool use_regular_copy = copying.use_safe_copy) { 43 | if (entry.is_directory()) 44 | fs::copy(entry.path(), target, copying.opts); 45 | else 46 | fs::copy(entry.path(), target, use_regular_copy ? copying.opts : (copying.opts | fs::copy_options::create_hard_links)); 47 | }; 48 | try { 49 | loadItem(); 50 | } catch (const fs::filesystem_error& e) { 51 | if (!copying.use_safe_copy && e.code() == std::errc::cross_device_link) loadItem(true); 52 | } 53 | } 54 | 55 | destination.applyIgnoreRules(); 56 | 57 | successes.clipboards++; 58 | } catch (const fs::filesystem_error& e) { 59 | copying.failedItems.emplace_back(destination_number, e.code()); 60 | } 61 | } 62 | 63 | stopIndicator(); 64 | 65 | if (std::find(destinations.begin(), destinations.end(), constants.default_clipboard_name) != destinations.end()) updateExternalClipboards(true); 66 | } 67 | 68 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/note.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void noteText() { 21 | if (copying.items.size() >= 1) { 22 | if (copying.items.at(0).string() == "") { 23 | fs::remove(path.metadata.notes); 24 | if (output_silent || confirmation_silent) return; 25 | stopIndicator(); 26 | fprintf(stderr, "%s", formatColors("[success][inverse] ✔ [noinverse] Removed note[blank]\n").data()); 27 | } else { 28 | fs::remove(path.metadata.notes); 29 | for (size_t i = 0; i < copying.items.size(); i++) { 30 | writeToFile(path.metadata.notes, copying.items.at(i).string(), true); 31 | if (i != copying.items.size() - 1) writeToFile(path.metadata.notes, " ", true); 32 | } 33 | if (output_silent || confirmation_silent) return; 34 | stopIndicator(); 35 | fprintf(stderr, formatColors("[success][inverse] ✔ [noinverse] Saved note \"%s\"[blank]\n").data(), fileContents(path.metadata.notes).value().data()); 36 | } 37 | } else if (copying.items.empty()) { 38 | if (fs::is_regular_file(path.metadata.notes)) { 39 | std::string content(fileContents(path.metadata.notes).value()); 40 | if (is_tty.out) { 41 | stopIndicator(); 42 | printf(formatColors("[info]┃ Note for this clipboard: %s[blank]\n").data(), content.data()); 43 | } else 44 | printf(formatColors("%s").data(), content.data()); 45 | } else { 46 | stopIndicator(); 47 | fprintf(stderr, "%s", formatColors("[info]┃ There is no note for this clipboard.[blank]\n").data()); 48 | } 49 | } else 50 | error_exit("%s", formatColors("[error][inverse] ✘ [noinverse] You can't add multiple items to a note. [help]⬤ Try providing a single piece of text instead.[blank]\n")); 51 | } 52 | 53 | void notePipe() { 54 | std::string content(pipedInContent()); 55 | writeToFile(path.metadata.notes, content); 56 | if (output_silent || confirmation_silent) return; 57 | stopIndicator(); 58 | fprintf(stderr, formatColors("[success][inverse] ✔ [noinverse] Saved note \"%s\"[blank]\n").data(), content.data()); 59 | exit(EXIT_SUCCESS); 60 | } 61 | 62 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/pipeinout.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | #if defined(_WIN32) || defined(_WIN64) 19 | #include 20 | #include 21 | #include 22 | #endif 23 | 24 | namespace PerformAction { 25 | 26 | void pipeIn() { 27 | copying.buffer = pipedInContent(); 28 | writeToFile(path.data.raw, copying.buffer); 29 | if (action == Action::Cut) writeToFile(path.metadata.originals, path.data.raw.string()); 30 | } 31 | 32 | void pipeOut() { 33 | for (const auto& entry : fs::recursive_directory_iterator(path.data)) { 34 | std::string content(fileContents(entry.path()).value()); 35 | #if !defined(_WIN32) && !defined(_WIN64) 36 | int len = write(fileno(stdout), content.data(), content.size()); 37 | if (len < 0) throw std::runtime_error("write() failed"); 38 | #elif defined(_WIN32) || defined(_WIN64) 39 | _setmode(_fileno(stdout), _O_BINARY); 40 | fwrite(content.data(), sizeof(char), content.size(), stdout); 41 | #endif 42 | fflush(stdout); 43 | successes.bytes += content.size(); 44 | } 45 | removeOldFiles(); 46 | } 47 | 48 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/redo.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | void redo() {} 20 | 21 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/remove.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void removeRegex() { 21 | std::vector regexes; 22 | if (io_type == IOType::Pipe) 23 | regexes.emplace_back(pipedInContent()); 24 | else 25 | std::transform(copying.items.begin(), copying.items.end(), std::back_inserter(regexes), [](const auto& item) { return std::regex(item.string()); }); 26 | 27 | if (path.holdsRawDataInCurrentEntry()) { 28 | std::string content(fileContents(path.data.raw).value()); 29 | size_t oldLength = content.size(); 30 | 31 | for (const auto& pattern : regexes) 32 | content = std::regex_replace(content, pattern, ""); 33 | successes.bytes += oldLength - content.size(); 34 | 35 | if (oldLength != content.size()) 36 | writeToFile(path.data.raw, content); 37 | else 38 | error_exit( 39 | "%s", 40 | formatColors("[error][inverse] ✘ [noinverse] CB couldn't match your pattern(s) against anything. [help]⬤ Try using a different pattern instead or check what's " 41 | "stored.[blank]\n") 42 | ); 43 | } else { 44 | for (const auto& entry : fs::directory_iterator(path.data)) { 45 | for (const auto& pattern : regexes) { 46 | if (std::regex_match(entry.path().filename().string(), pattern)) { 47 | try { 48 | fs::remove_all(entry.path()); 49 | incrementSuccessesForItem(entry.path()); 50 | } catch (const fs::filesystem_error& e) { 51 | copying.failedItems.emplace_back(entry.path().filename().string(), e.code()); 52 | } 53 | } 54 | } 55 | } 56 | if (successes.directories == 0 && successes.files == 0) 57 | error_exit( 58 | "%s", 59 | formatColors("[error][inverse] ✘ [noinverse] CB couldn't match your pattern(s) against anything. [help]⬤ Try using a different pattern instead or check what's " 60 | "stored.[blank]\n") 61 | ); 62 | } 63 | } 64 | 65 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/share.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2024 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | void share() {} 20 | 21 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/swap.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | 20 | void swap() { 21 | if (copying.items.size() > 1) 22 | error_exit( 23 | formatColors("[error][inverse] ✘ [noinverse] You can only swap one clipboard at a time. [help]Try making sure there's only one other clipboard specified, like [bold]%s swap " 24 | "5[nobold] or [bold]%s swap3 0[nobold].[blank]\n"), 25 | clipboard_invocation, 26 | clipboard_invocation 27 | ); 28 | 29 | std::string destination_name = copying.items.empty() ? std::string(constants.default_clipboard_name) : copying.items.at(0).string(); 30 | 31 | if (destination_name == clipboard_name) 32 | error_exit( 33 | formatColors("[error][inverse] ✘ [noinverse] You can't swap a clipboard with itself. [help]Try choosing a different clipboard to swap with, like [bold]%s swap 5[nobold] or " 34 | "[bold]%s swap3 0[nobold].[blank]\n"), 35 | clipboard_invocation, 36 | clipboard_invocation 37 | ); 38 | 39 | Clipboard destination(destination_name); 40 | 41 | fs::path swapTargetSource(path.data); 42 | swapTargetSource.replace_extension("swap"); 43 | 44 | fs::path swapTargetDestination(destination.data); 45 | swapTargetDestination.replace_extension("swap"); 46 | 47 | try { 48 | fs::copy(destination.data, swapTargetSource, fs::copy_options::recursive); 49 | fs::copy(path.data, swapTargetDestination, fs::copy_options::recursive); 50 | 51 | fs::remove_all(path.data); 52 | fs::remove_all(destination.data); 53 | 54 | fs::rename(swapTargetSource, path.data); 55 | fs::rename(swapTargetDestination, destination.data); 56 | } catch (const fs::filesystem_error& e) { 57 | copying.failedItems.emplace_back(destination_name, e.code()); 58 | } 59 | 60 | stopIndicator(); 61 | 62 | if (!output_silent && !confirmation_silent) 63 | fprintf(stderr, formatColors("[success][inverse] ✔ [noinverse] Swapped clipboard %s with %s[blank]\n").data(), clipboard_name.data(), destination_name.data()); 64 | 65 | if (destination_name == constants.default_clipboard_name) updateExternalClipboards(true); 66 | } 67 | 68 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/actions/undo.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | namespace PerformAction { 19 | void undo() {} 20 | 21 | } // namespace PerformAction -------------------------------------------------------------------------------- /src/cb/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "clipboard.hpp" 17 | 18 | int main(int argc, char* argv[]) { 19 | try { 20 | setupHandlers(); 21 | 22 | setupVariables(argc, argv); 23 | 24 | setupTerminal(); 25 | 26 | setLocale(); 27 | 28 | setClipboardAttributes(); 29 | 30 | setFlags(); 31 | 32 | startIndicator(); 33 | 34 | verifyClipboardName(); 35 | 36 | setFilepaths(); 37 | 38 | action = getAction(); 39 | 40 | if (auto pos = std::find_if(arguments.begin(), arguments.end(), [](const auto& arg) { return arg == "--"; }); pos != arguments.end()) arguments.erase(pos); 41 | 42 | copying.items.assign(arguments.begin(), arguments.end()); 43 | 44 | io_type = getIOType(); 45 | 46 | verifyAction(); 47 | 48 | #if defined(__linux__) 49 | setupGUIClipboardDaemon(); 50 | syncWithRemoteClipboard(); 51 | if (action != Action::Info) path.getLock(); 52 | #else 53 | if (action != Action::Info) path.getLock(); 54 | syncWithExternalClipboards(); 55 | #endif 56 | 57 | fixMissingItems(); 58 | 59 | ignoreItemsPreemptively(copying.items); 60 | 61 | checkForNoItems(); 62 | 63 | if (needsANewEntry()) path.makeNewEntry(); 64 | 65 | (clipboard_state.exchange(ClipboardState::Action), cv.notify_one()); 66 | 67 | (fs::create_directories(global_path.temporary), fs::create_directories(global_path.persistent)); 68 | 69 | if (io_type != IOType::Text) deduplicate(copying.items); 70 | 71 | checkItemSize(totalItemSize()); 72 | 73 | checkClipboardScriptEligibility(); 74 | 75 | runClipboardScript(); 76 | 77 | performAction(); 78 | 79 | runClipboardScript(); 80 | 81 | if (isAWriteAction()) path.applyIgnoreRules(); 82 | 83 | copying.mime = getMIMEType(); 84 | 85 | updateExternalClipboards(); 86 | 87 | if (!copying.failedItems.empty()) clipboard_state = ClipboardState::Error; 88 | 89 | stopIndicator(); 90 | 91 | deduplicate(copying.failedItems); 92 | 93 | showFailures(); 94 | 95 | showSuccesses(); 96 | 97 | path.trimHistoryEntries(); 98 | } catch (const std::exception& e) { 99 | clipboard_state = ClipboardState::Error; 100 | stopIndicator(); 101 | fprintf(stderr, internal_error_message().data(), e.what()); 102 | exit(EXIT_FAILURE); 103 | } 104 | if (clipboard_state == ClipboardState::Error) 105 | exit(EXIT_FAILURE); 106 | else 107 | exit(EXIT_SUCCESS); 108 | } -------------------------------------------------------------------------------- /src/cb/src/platforms/android.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include 17 | #include 18 | #include 19 | 20 | #include "../clipboard.hpp" 21 | 22 | const bool GUIClipboardSupportsCut = false; 23 | 24 | ClipboardContent getGUIClipboard(const std::string& requested_mime) { 25 | return ClipboardContent(); 26 | } 27 | 28 | void writeToGUIClipboard(const ClipboardContent& clipboard) { 29 | if (clipboard.type() == ClipboardContentType::Text || clipboard.type() == ClipboardContentType::Binary) { 30 | 31 | } else if (clipboard.type() == ClipboardContentType::Paths) { 32 | } 33 | } 34 | 35 | bool playAsyncSoundEffect(const std::valarray& samples) { 36 | return false; 37 | } -------------------------------------------------------------------------------- /src/cb/src/platforms/bsd.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | bool playAsyncSoundEffect(const std::valarray& samples) { 19 | return false; 20 | } -------------------------------------------------------------------------------- /src/cb/src/platforms/haiku.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "../clipboard.hpp" 22 | 23 | const bool GUIClipboardSupportsCut = false; 24 | 25 | ClipboardContent getGUIClipboard(const std::string& requested_mime) { 26 | std::unique_ptr gui_clipboard = std::make_unique("system"); 27 | if (!gui_clipboard->Lock()) return {}; 28 | BMessage* content = gui_clipboard->Data(); 29 | gui_clipboard->Unlock(); 30 | const char* temp; 31 | ssize_t tempLength = 0; 32 | if (!content->FindData("text/plain", B_MIME_TYPE, (const void**)&temp, &tempLength)) { 33 | std::string CBcontent(temp, tempLength); 34 | return ClipboardContent(CBcontent); 35 | } 36 | return {}; 37 | } 38 | 39 | void writeToGUIClipboard(const ClipboardContent& clipboard) { 40 | std::unique_ptr gui_clipboard = std::make_unique("system"); 41 | if (!gui_clipboard->Lock()) return; 42 | gui_clipboard->Clear(); 43 | BMessage* content = (BMessage*)NULL; 44 | if (content = gui_clipboard->Data()) { 45 | if (clipboard.type() == ClipboardContentType::Text || clipboard.type() == ClipboardContentType::Binary) { 46 | content->AddData("text/plain", B_MIME_TYPE, clipboard.text().data(), clipboard.text().length()); 47 | } else if (clipboard.type() == ClipboardContentType::Paths) { 48 | } 49 | gui_clipboard->Commit(); 50 | } 51 | gui_clipboard->Unlock(); 52 | } 53 | 54 | bool playAsyncSoundEffect(const std::valarray& samples) { 55 | return false; 56 | } -------------------------------------------------------------------------------- /src/cb/src/platforms/linux.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | #if defined(USE_ALSA) 18 | #include 19 | #endif 20 | 21 | void dummy_handler(const char* file, int line, const char* function, int err, const char* fmt, ...) {} 22 | 23 | bool playAsyncSoundEffect(const std::valarray& samples) { 24 | #if defined(USE_ALSA) 25 | if (fork()) return true; 26 | 27 | snd_lib_error_set_handler(dummy_handler); // suppress errors in console 28 | 29 | snd_pcm_t* device; 30 | if (snd_pcm_open(&device, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) std::_Exit(EXIT_FAILURE); 31 | snd_pcm_hw_params_t* params; 32 | snd_pcm_hw_params_alloca(¶ms); 33 | snd_pcm_hw_params_any(device, params); 34 | snd_pcm_hw_params_set_access(device, params, SND_PCM_ACCESS_RW_INTERLEAVED); 35 | snd_pcm_hw_params_set_format(device, params, SND_PCM_FORMAT_S16_LE); 36 | snd_pcm_hw_params_set_channels(device, params, 2); 37 | snd_pcm_hw_params_set_rate(device, params, 44100, 0); 38 | snd_pcm_hw_params_set_periods(device, params, 16, 0); 39 | snd_pcm_hw_params_set_period_time(device, params, 1024, 0); 40 | snd_pcm_hw_params(device, params); 41 | 42 | snd_pcm_writei(device, &(samples[0]), samples.size() / 2); 43 | 44 | snd_pcm_drain(device); 45 | 46 | snd_pcm_close(device); 47 | 48 | std::_Exit(EXIT_SUCCESS); 49 | #else 50 | return false; 51 | #endif 52 | } 53 | -------------------------------------------------------------------------------- /src/cb/src/platforms/macos.mm: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import "../clipboard.hpp" 22 | 23 | const bool GUIClipboardSupportsCut = false; 24 | 25 | static std::vector fileContent() { 26 | NSArray *classes = @[ [NSURL class] ]; 27 | if ([[NSPasteboard generalPasteboard] canReadObjectForClasses:classes options:nil]) { 28 | NSArray *files = [[NSPasteboard generalPasteboard] readObjectsForClasses:classes options:nil]; 29 | std::vector stringArray; 30 | for (NSURL *fileURL in files) { 31 | stringArray.push_back([[fileURL path] UTF8String]); 32 | } 33 | return stringArray; 34 | } 35 | return {}; 36 | } 37 | 38 | static std::string textContent() { 39 | NSArray *classes = @[ [NSString class], [NSAttributedString class] ]; 40 | if ([[NSPasteboard generalPasteboard] canReadObjectForClasses:classes options:nil]) { 41 | NSString *text = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]; 42 | return [text UTF8String]; 43 | } 44 | return ""; 45 | } 46 | 47 | ClipboardContent getGUIClipboard(const std::string& requested_mime) { 48 | (void)requested_mime; 49 | auto files = fileContent(); 50 | if (files.size() > 0) { 51 | std::vector fileVector; 52 | for (auto &file : files) { 53 | fileVector.push_back(file); 54 | } 55 | ClipboardPaths paths(fileVector); 56 | return ClipboardContent(paths); 57 | } else if (auto text = textContent(); text != "") { 58 | return ClipboardContent(text); 59 | } 60 | return ClipboardContent(); 61 | } 62 | 63 | void writeToGUIClipboard(const ClipboardContent& clipboard) { 64 | [[NSPasteboard generalPasteboard] clearContents]; 65 | if (clipboard.type() == ClipboardContentType::Text || clipboard.type() == ClipboardContentType::Binary) { 66 | [[NSPasteboard generalPasteboard] setString:@(clipboard.text().c_str()) forType:NSPasteboardTypeString]; 67 | } else if (clipboard.type() == ClipboardContentType::Paths) { 68 | NSMutableArray *fileArray = [NSMutableArray new]; 69 | for (auto const& path : clipboard.paths().paths()) { 70 | [fileArray addObject:[NSURL fileURLWithPath:@(path.c_str())]]; 71 | } 72 | [[NSPasteboard generalPasteboard] writeObjects:fileArray]; 73 | } else { 74 | // Write blank content 75 | [[NSPasteboard generalPasteboard] setString:@"" forType:NSPasteboardTypeString]; 76 | } 77 | } 78 | 79 | bool playAsyncSoundEffect(const std::valarray& samples) { 80 | (void)samples; 81 | return false; 82 | } -------------------------------------------------------------------------------- /src/cb/src/platforms/windows.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | #include "../clipboard.hpp" 18 | #include 19 | #include 20 | #include 21 | 22 | namespace fs = std::filesystem; 23 | 24 | template 25 | void decodeWindowsDropfilesPaths(void* filesList, std::vector& paths) { 26 | 27 | auto data = static_cast(filesList); 28 | std::vector currentPath; 29 | 30 | while (true) { 31 | auto c = *data++; 32 | currentPath.push_back(c); 33 | 34 | if (c == 0) { 35 | if (currentPath.size() == 1) { 36 | break; 37 | } 38 | 39 | paths.emplace_back(¤tPath[0]); 40 | currentPath.clear(); 41 | } 42 | } 43 | } 44 | 45 | void onWindowsError(const std::string_view function); 46 | std::vector getWindowsClipboardDataFiles(void* clipboardPointer); 47 | std::string getWindowsClipboardDataPipe(void* clipboardPointer); 48 | void setWindowsClipboardDataPipe(); 49 | void setWindowsClipboardDataFiles(); 50 | ClipboardContent getGUIClipboard(const std::string& requested_mime); 51 | void writeToGUIClipboard(const ClipboardContent& clipboard); 52 | -------------------------------------------------------------------------------- /src/cb/src/platforms/windows.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UTF-8 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/cb/src/sounds/error.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/cb/src/sounds/error.pcm -------------------------------------------------------------------------------- /src/cb/src/sounds/error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/cb/src/sounds/error.wav -------------------------------------------------------------------------------- /src/cb/src/sounds/success.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/cb/src/sounds/success.pcm -------------------------------------------------------------------------------- /src/cb/src/sounds/success.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/cb/src/sounds/success.wav -------------------------------------------------------------------------------- /src/cb/src/utils/cowcopy.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2024 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | #if defined(__linux__) 18 | #include 19 | #include 20 | #endif 21 | -------------------------------------------------------------------------------- /src/cb/src/utils/directorysize.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2024 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | #if defined(UNIX_OR_UNIX_LIKE) 19 | #include 20 | #endif 21 | 22 | size_t directoryOverhead(const fs::path& directory) { 23 | #if defined(UNIX_OR_UNIX_LIKE) 24 | struct stat info; 25 | if (stat(directory.string().data(), &info) != 0) return 0; 26 | return info.st_size; 27 | #else 28 | return 0; 29 | #endif 30 | } 31 | 32 | thread_local size_t size = 0; // thread_local because multiple threads could call ftwHandler 33 | 34 | #if defined(UNIX_OR_UNIX_LIKE) 35 | int ftwHandler(const char* fpath, const struct stat* sb, int typeflag) { 36 | size += sb->st_size; 37 | return 0; 38 | } 39 | #endif 40 | 41 | size_t totalDirectorySize(const fs::path& directory) { 42 | size = directoryOverhead(directory); 43 | #if defined(UNIX_OR_UNIX_LIKE) 44 | ftw(directory.string().data(), ftwHandler, 1); 45 | #else 46 | for (const auto& entry : fs::recursive_directory_iterator(directory)) 47 | try { 48 | size += entry.is_directory() ? directoryOverhead(entry) : entry.file_size(); 49 | } catch (const fs::filesystem_error& e) { 50 | if (e.code() != std::errc::no_such_file_or_directory) throw e; 51 | } 52 | #endif 53 | return size; 54 | } -------------------------------------------------------------------------------- /src/cb/src/utils/distance.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | size_t levenshteinDistance(const std::string_view& one, const std::string_view& two) { 19 | if (one == two) return 0; 20 | 21 | if (one.empty()) return two.size(); 22 | if (two.empty()) return one.size(); 23 | 24 | std::vector> matrix(one.size() + 1, std::vector(two.size() + 1)); 25 | 26 | for (size_t i = 0; i <= one.size(); i++) 27 | matrix.at(i).at(0) = i; 28 | 29 | for (size_t j = 0; j <= two.size(); j++) 30 | matrix.at(0).at(j) = j; 31 | 32 | for (size_t i = 1; i <= one.size(); i++) { 33 | for (size_t j = 1; j <= two.size(); j++) { 34 | if (one.at(i - 1) == two.at(j - 1)) 35 | matrix.at(i).at(j) = matrix.at(i - 1).at(j - 1); 36 | else 37 | matrix.at(i).at(j) = std::min({matrix.at(i - 1).at(j - 1), matrix.at(i - 1).at(j), matrix.at(i).at(j - 1)}) + 1; 38 | } 39 | } 40 | 41 | return matrix.at(one.size()).at(two.size()); 42 | }; -------------------------------------------------------------------------------- /src/cb/src/utils/editors.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | 18 | std::optional findUsableEditor() { 19 | auto preferredEditor = []() -> std::optional { 20 | if (!copying.items.empty()) return copying.items.at(0).string(); 21 | if (auto editor = getenv("CLIPBOARD_EDITOR"); editor != nullptr) return editor; 22 | if (auto editor = getenv("EDITOR"); editor != nullptr) return editor; 23 | if (auto editor = getenv("VISUAL"); editor != nullptr) return editor; 24 | return std::nullopt; 25 | }; 26 | 27 | auto fallbackEditor = []() -> std::optional { 28 | constexpr std::array fallbacks {"nano", "vim", "nvim", "micro", "code", "gedit", "vi", "emacs", "subl", "sublime", "atom", 29 | "gedit", "kate", "mousepad", "leafpad", "pluma", "geany", "notepad.exe", "notepad++.exe", "wordpad.exe", "word.exe"}; 30 | 31 | std::string pathContent(getenv("PATH")); 32 | std::vector paths; 33 | 34 | // split paths by : or ; (: for posix, ; for windows) 35 | auto strings = regexSplit(pathContent, std::regex("[:;]")); 36 | std::transform(strings.begin(), strings.end(), std::back_inserter(paths), [](const std::string& path) { return fs::path(path); }); 37 | 38 | for (const auto& path : paths) 39 | for (const auto& fallback : fallbacks) 40 | if (fs::exists(path / fallback)) return fallback; 41 | 42 | return std::nullopt; 43 | }; 44 | 45 | auto editor = preferredEditor(); 46 | 47 | if (!editor) editor = fallbackEditor(); 48 | 49 | return editor; 50 | } -------------------------------------------------------------------------------- /src/cb/src/utils/files.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "../clipboard.hpp" 17 | #include 18 | 19 | std::optional fileContents(const fs::path& path) { 20 | #if defined(UNIX_OR_UNIX_LIKE) 21 | errno = 0; 22 | int fd = open(path.string().data(), O_RDONLY); 23 | if (fd == -1) { 24 | if (errno == ENOENT) 25 | return std::nullopt; 26 | else 27 | throw std::runtime_error("Couldn't open file " + path.string() + ": " + std::strerror(errno)); 28 | } 29 | std::string contents; 30 | #if defined(__linux__) || defined(__FreeBSD__) 31 | std::array buffer; 32 | #elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) 33 | std::array buffer; 34 | #else 35 | std::array buffer; 36 | #endif 37 | ssize_t bytes_read; 38 | errno = 0; 39 | while ((bytes_read = read(fd, buffer.data(), buffer.size())) > 0) { 40 | contents.append(buffer.data(), bytes_read); 41 | if (bytes_read < buffer.size() && errno == 0) break; // check if we reached EOF early and not due to an error 42 | } 43 | close(fd); 44 | return contents; 45 | #else 46 | std::stringstream buffer; 47 | std::ifstream file(path, std::ios::binary); 48 | if (!file.is_open()) return std::nullopt; 49 | buffer << file.rdbuf(); 50 | return buffer.str(); 51 | #endif 52 | } 53 | 54 | std::vector fileLines(const fs::path& path, bool includeEmptyLines) { 55 | std::vector lines; 56 | auto content = fileContents(path); 57 | if (!content) return lines; 58 | std::istringstream stream(*content); 59 | for (std::string line; std::getline(stream, line);) { 60 | if (!line.empty() || includeEmptyLines) lines.emplace_back(line); 61 | } 62 | return lines; 63 | } 64 | 65 | size_t writeToFile(const fs::path& path, const std::string& content, bool append) { 66 | std::ofstream file(path, append ? std::ios::app : std::ios::trunc | std::ios::binary); 67 | file << content; 68 | return content.size(); 69 | } -------------------------------------------------------------------------------- /src/cbwayland/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") 2 | set(GENERATED_INCLUDE_DIR "${GENERATED_DIR}/include") 3 | set(GENERATED_SRC_DIR "${GENERATED_DIR}/src") 4 | 5 | find_program(WAYLAND_SCANNER wayland-scanner REQUIRED) 6 | pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) 7 | 8 | set(XDG_SHELL_PROTOCOL "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml") 9 | set(GENERATED_XDG_SHELL_HEADER "${GENERATED_INCLUDE_DIR}/wayland-xdg-shell.hpp") 10 | set(GENERATED_XDG_SHELL_CODE "${GENERATED_SRC_DIR}/wayland-xdg-shell.c") 11 | 12 | file(MAKE_DIRECTORY 13 | "${GENERATED_INCLUDE_DIR}" 14 | "${GENERATED_SRC_DIR}" 15 | ) 16 | 17 | add_custom_command( 18 | OUTPUT "${GENERATED_XDG_SHELL_HEADER}" 19 | COMMAND "${WAYLAND_SCANNER}" 20 | ARGS 21 | --strict 22 | client-header 23 | "${XDG_SHELL_PROTOCOL}" 24 | "${GENERATED_XDG_SHELL_HEADER}" 25 | ) 26 | add_custom_command( 27 | OUTPUT "${GENERATED_XDG_SHELL_CODE}" 28 | COMMAND "${WAYLAND_SCANNER}" 29 | ARGS 30 | --strict 31 | private-code 32 | "${XDG_SHELL_PROTOCOL}" 33 | "${GENERATED_XDG_SHELL_CODE}" 34 | ) 35 | add_custom_target(cbwayland_generatedheaders 36 | DEPENDS "${GENERATED_XDG_SHELL_HEADER}" 37 | ) 38 | 39 | add_library(cbwayland MODULE 40 | src/fd.cpp 41 | src/wayland.cpp 42 | 43 | src/objects/buffer.cpp 44 | src/objects/callback.cpp 45 | src/objects/data_device.cpp 46 | src/objects/data_offer.cpp 47 | src/objects/data_source.cpp 48 | src/objects/display.cpp 49 | src/objects/keyboard.cpp 50 | src/objects/registry.cpp 51 | src/objects/seat.cpp 52 | src/objects/shm.cpp 53 | src/objects/shm_pool.cpp 54 | src/objects/surface.cpp 55 | src/objects/xdg_surface.cpp 56 | src/objects/xdg_toplevel.cpp 57 | src/objects/xdg_wm_base.cpp 58 | 59 | "${GENERATED_XDG_SHELL_CODE}" 60 | ) 61 | add_dependencies(cbwayland cbwayland_generatedheaders) 62 | 63 | enable_lto(cbwayland) 64 | 65 | target_link_libraries(cbwayland 66 | ${WAYLAND_CLIENT_LIBRARIES} 67 | gui 68 | ) 69 | target_include_directories(cbwayland PRIVATE 70 | ${WAYLAND_CLIENT_INCLUDE_DIRS} 71 | ${GENERATED_INCLUDE_DIR} 72 | ) 73 | 74 | install(TARGETS cbwayland LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 75 | -------------------------------------------------------------------------------- /src/cbwayland/src/exception.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include 19 | 20 | class WlException : public SimpleException { 21 | using SimpleException::SimpleException; 22 | }; 23 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/all.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "buffer.hpp" 19 | #include "callback.hpp" 20 | #include "compositor.hpp" 21 | #include "data_device.hpp" 22 | #include "data_device_manager.hpp" 23 | #include "data_offer.hpp" 24 | #include "data_source.hpp" 25 | #include "display.hpp" 26 | #include "keyboard.hpp" 27 | #include "registry.hpp" 28 | #include "seat.hpp" 29 | #include "shm.hpp" 30 | #include "shm_pool.hpp" 31 | #include "surface.hpp" 32 | #include "xdg_surface.hpp" 33 | #include "xdg_toplevel.hpp" 34 | #include "xdg_wm_base.hpp" 35 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/buffer.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "buffer.hpp" 17 | #include "all.hpp" 18 | 19 | WlBuffer::WlBuffer(std::unique_ptr&& pool, std::int32_t offset, std::int32_t width, std::int32_t height, std::int32_t stride, wl_shm_format format) 20 | : WlObject {wl_shm_pool_create_buffer(getValue(pool), offset, width, height, stride, format)} 21 | , m_shmPool {std::move(pool)} {} 22 | 23 | std::unique_ptr WlBuffer::fromMemfd(const WlRegistry& registry, std::int32_t width, std::int32_t height, std::int32_t stride, wl_shm_format format) { 24 | if (!registry.get().supports(format)) { 25 | throw WlException("wl_shm doesn't support format ", format); 26 | } 27 | 28 | auto size = stride * height; 29 | return std::make_unique(WlShmPool::fromMemfd(registry, size), 0, width, height, stride, format); 30 | } 31 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/buffer.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | struct WlBufferSpec { 24 | WL_SPEC_BASE(wl_buffer, 1) 25 | WL_SPEC_DESTROY(wl_buffer) 26 | }; 27 | 28 | class WlBuffer : public WlObject { 29 | private: 30 | std::unique_ptr m_shmPool; 31 | 32 | public: 33 | WlBuffer(std::unique_ptr&&, std::int32_t offset, std::int32_t width, std::int32_t height, std::int32_t stride, wl_shm_format); 34 | 35 | static std::unique_ptr fromMemfd(const WlRegistry&, std::int32_t width, std::int32_t height, std::int32_t stride, wl_shm_format); 36 | }; 37 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/callback.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "callback.hpp" 17 | #include "all.hpp" 18 | 19 | decltype(WlCallbackSpec::listener) WlCallbackSpec::listener { 20 | .done = &eventHandler<&WlCallback::onDone>, 21 | }; 22 | 23 | WlCallback::WlCallback(const WlDisplay& display) : WlObject {wl_display_sync(display.value())} {} 24 | 25 | void WlCallback::onDone(std::uint32_t serial) { 26 | m_serial = serial; 27 | } 28 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/callback.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | struct WlCallbackSpec { 24 | WL_SPEC_BASE(wl_callback, 1) 25 | WL_SPEC_DESTROY(wl_callback) 26 | WL_SPEC_LISTENER(wl_callback) 27 | }; 28 | 29 | class WlCallback : public WlObject { 30 | friend WlCallbackSpec; 31 | 32 | std::optional m_serial {}; 33 | 34 | public: 35 | explicit WlCallback(const WlDisplay&); 36 | 37 | [[nodiscard]] inline bool hasSerial() const { return m_serial.has_value(); } 38 | [[nodiscard]] inline std::uint32_t serial() const { return m_serial.value_or(0); } 39 | 40 | private: 41 | void onDone(std::uint32_t); 42 | }; 43 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/compositor.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | struct WlCompositorSpec { 22 | WL_SPEC_BASE(wl_compositor, 5) 23 | WL_SPEC_DESTROY(wl_compositor) 24 | }; 25 | 26 | class WlCompositor : public WlObject { 27 | public: 28 | explicit WlCompositor(obj_t* value) : WlObject {value} {} 29 | }; 30 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_device.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "data_device.hpp" 17 | #include "all.hpp" 18 | 19 | #include 20 | 21 | wl_data_device_listener WlDataDeviceSpec::listener { 22 | .data_offer = &eventHandler<&WlDataDevice::onDataOffer>, 23 | .enter = &noHandler, 24 | .leave = &noHandler, 25 | .motion = &noHandler, 26 | .drop = &noHandler, 27 | .selection = &eventHandler<&WlDataDevice::onSelection>, 28 | }; 29 | 30 | WlDataDevice::WlDataDevice(const WlDataDeviceManager& manager, const WlSeat& seat) : WlObject {wl_data_device_manager_get_data_device(manager.value(), seat.value())} { 31 | debugStream << "Created a data device for seat " << seat.name() << std::endl; 32 | } 33 | 34 | WlDataDevice::WlDataDevice(const WlRegistry& registry) 35 | : WlDataDevice { 36 | registry.get(), 37 | registry.get(), 38 | } {} 39 | 40 | void WlDataDevice::onDataOffer(wl_data_offer* offer) { 41 | if (offer == nullptr) { 42 | debugStream << "Received a null data offer, ignoring" << std::endl; 43 | return; 44 | } 45 | 46 | m_bufferedOffer = std::make_unique(offer); 47 | debugStream << "Got a new offer" << std::endl; 48 | } 49 | 50 | void WlDataDevice::onSelection(wl_data_offer* offer) { 51 | m_receivedSelectionEvent = true; 52 | 53 | if (offer == nullptr) { 54 | debugStream << "Selection was cleared" << std::endl; 55 | m_bufferedOffer.reset(); 56 | m_selectionOffer.reset(); 57 | return; 58 | } 59 | 60 | if (!m_bufferedOffer) { 61 | debugStream << "Got a new selection but its offer wasn't initialized before, ignoring" << std::endl; 62 | return; 63 | } 64 | 65 | if (getValue(m_bufferedOffer) != offer) { 66 | debugStream << "Got a selection but its offer didn't match the one that was initialized earlier, ignoring" << std::endl; 67 | return; 68 | } 69 | 70 | m_selectionOffer.reset(); 71 | m_selectionOffer.swap(m_bufferedOffer); 72 | debugStream << "Offer was promoted to selection" << std::endl; 73 | } 74 | 75 | void WlDataDevice::setSelection(const WlDataSource& source, std::uint32_t serial) const { 76 | wl_data_device_set_selection(value(), source.value(), serial); 77 | } 78 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_device.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | struct WlDataDeviceSpec { 22 | WL_SPEC_BASE(wl_data_device, 3) 23 | WL_SPEC_RELEASE(wl_data_device) 24 | WL_SPEC_LISTENER(wl_data_device) 25 | }; 26 | 27 | class WlDataDevice : public WlObject { 28 | friend WlDataDeviceSpec; 29 | 30 | bool m_receivedSelectionEvent {false}; 31 | std::unique_ptr m_bufferedOffer {}; 32 | std::unique_ptr m_selectionOffer {}; 33 | 34 | public: 35 | explicit WlDataDevice(const WlDataDeviceManager&, const WlSeat&); 36 | explicit WlDataDevice(const WlRegistry&); 37 | 38 | [[nodiscard]] inline bool receivedSelectionEvent() const { return m_receivedSelectionEvent; } 39 | [[nodiscard]] inline bool hasSelectionOffer() const { return m_selectionOffer != nullptr; } 40 | [[nodiscard]] inline std::unique_ptr releaseSelectionOffer() { return std::move(m_selectionOffer); } 41 | 42 | void setSelection(const WlDataSource&, std::uint32_t serial) const; 43 | 44 | private: 45 | void onDataOffer(wl_data_offer*); 46 | void onSelection(wl_data_offer*); 47 | }; 48 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_device_manager.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | struct WlDataDeviceManagerSpec { 22 | WL_SPEC_BASE(wl_data_device_manager, 3) 23 | WL_SPEC_DESTROY(wl_data_device_manager) 24 | }; 25 | 26 | class WlDataDeviceManager : public WlObject { 27 | public: 28 | explicit WlDataDeviceManager(obj_t* value) : WlObject {value} {} 29 | }; 30 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_offer.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "data_offer.hpp" 17 | #include "all.hpp" 18 | 19 | wl_data_offer_listener WlDataOfferSpec::listener { 20 | .offer = &eventHandler<&WlDataOffer::onOffer>, 21 | .source_actions = &noHandler, 22 | .action = &noHandler, 23 | }; 24 | 25 | void WlDataOffer::onOffer(const char* mime) { 26 | m_mimeTypes.emplace(mime); 27 | } 28 | 29 | void WlDataOffer::receive(std::string_view mime, int fd) const { 30 | std::string mimeCopy {mime}; 31 | wl_data_offer_receive(value(), mimeCopy.c_str(), fd); 32 | } 33 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_offer.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | #include 23 | 24 | struct WlDataOfferSpec { 25 | WL_SPEC_BASE(wl_data_offer, 3) 26 | WL_SPEC_DESTROY(wl_data_offer) 27 | WL_SPEC_LISTENER(wl_data_offer) 28 | }; 29 | 30 | class WlDataOffer : public WlObject { 31 | friend WlDataOfferSpec; 32 | 33 | std::set m_mimeTypes {}; 34 | 35 | public: 36 | explicit WlDataOffer(obj_t* value) : WlObject {value} {} 37 | 38 | void receive(std::string_view mime, int fd) const; 39 | 40 | /** Performs an action for each MIME Type supported by this offer. */ 41 | template func_t> 42 | void forEachMimeType(func_t func) const; 43 | 44 | private: 45 | void onOffer(const char*); 46 | }; 47 | 48 | template func_t> 49 | void WlDataOffer::forEachMimeType(func_t func) const { 50 | for (auto&& value : m_mimeTypes) { 51 | func(value); 52 | } 53 | } -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_source.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "data_source.hpp" 17 | #include "all.hpp" 18 | 19 | #include 20 | 21 | wl_data_source_listener WlDataSourceSpec::listener { 22 | .target = &noHandler, 23 | .send = &eventHandler<&WlDataSource::onSend>, 24 | .cancelled = &eventHandler<&WlDataSource::onCancelled>, 25 | .dnd_drop_performed = &noHandler, 26 | .dnd_finished = &noHandler, 27 | .action = &noHandler, 28 | }; 29 | 30 | WlDataSource::WlDataSource(const WlDataDeviceManager& dataDeviceManager) : WlObject {wl_data_device_manager_create_data_source(dataDeviceManager.value())} {} 31 | 32 | WlDataSource::WlDataSource(const WlRegistry& registry) : WlDataSource {registry.get()} {} 33 | 34 | void WlDataSource::offer(std::string_view mime) const { 35 | std::string mimeCopy {mime}; 36 | wl_data_source_offer(value(), mimeCopy.c_str()); 37 | } 38 | 39 | void WlDataSource::onSend(const char* rawMime, std::int32_t rawFd) { 40 | std::string_view mime {rawMime}; 41 | Fd fd {rawFd}; 42 | if (m_sendCallback) { 43 | m_sendCallback(mime, std::move(fd)); 44 | } 45 | } 46 | 47 | void WlDataSource::onCancelled() { 48 | m_isCancelled = true; 49 | debugStream << "Data source was cancelled" << std::endl; 50 | } 51 | 52 | void WlDataSource::sendCallback(std::function&& callback) { 53 | m_sendCallback = std::move(callback); 54 | } 55 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/data_source.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "../fd.hpp" 19 | #include "forward.hpp" 20 | #include "spec.hpp" 21 | 22 | #include 23 | 24 | struct WlDataSourceSpec { 25 | WL_SPEC_BASE(wl_data_source, 3) 26 | WL_SPEC_DESTROY(wl_data_source) 27 | WL_SPEC_LISTENER(wl_data_source) 28 | }; 29 | 30 | class WlDataSource : public WlObject { 31 | friend WlDataSourceSpec; 32 | 33 | public: 34 | using sendCallback_t = void(std::string_view, Fd&&); 35 | 36 | private: 37 | bool m_isCancelled {false}; 38 | std::function m_sendCallback; 39 | 40 | public: 41 | explicit WlDataSource(const WlDataDeviceManager&); 42 | explicit WlDataSource(const WlRegistry&); 43 | 44 | [[nodiscard]] inline bool isCancelled() const { return m_isCancelled; } 45 | 46 | void sendCallback(std::function&&); 47 | void offer(std::string_view) const; 48 | 49 | private: 50 | void onSend(const char* mime, std::int32_t fd); 51 | void onCancelled(); 52 | }; 53 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/display.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | struct WlDisplaySpec { 24 | WL_SPEC_BASE(wl_display, 1) 25 | static constexpr auto deleter = &wl_display_disconnect; 26 | }; 27 | 28 | class WlDisplay : public WlObject { 29 | 30 | void throwIfError() const; 31 | void flush() const; 32 | void dispatchPending() const; 33 | void readEvents() const; 34 | void pollWithTimeout(short events) const; 35 | 36 | public: 37 | explicit WlDisplay(); 38 | 39 | void roundtrip() const; 40 | void dispatch() const; 41 | void dispatchWithTimeout() const; 42 | 43 | /** 44 | * Loops dispatch() until a certain predicate is met. 45 | * Throws if the operation takes too long. 46 | */ 47 | template 48 | void dispatchUntil(predicate_t predicate) const; 49 | 50 | /** 51 | * Gets the next event serial from the Wayland server. 52 | * Requires a back-and-forth between the client and the server and may 53 | * dispatch other events in the meantime. 54 | */ 55 | std::uint32_t getSerial() const; 56 | }; 57 | 58 | template 59 | void WlDisplay::dispatchUntil(predicate_t predicate) const { 60 | using namespace std::literals; 61 | constexpr auto maxWaitTime = 5s; 62 | 63 | throwIfError(); 64 | 65 | auto start = std::chrono::steady_clock::now(); 66 | while (!predicate()) { 67 | dispatchWithTimeout(); 68 | 69 | const auto time = std::chrono::steady_clock::now() - start; 70 | if (time > maxWaitTime) { 71 | throw WlException("Timed out waiting for the Wayland server to reply"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/forward.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | class WlBuffer; 19 | class WlCallback; 20 | class WlCompositor; 21 | class WlDataDevice; 22 | class WlDataDeviceManager; 23 | class WlDataOffer; 24 | class WlDataSource; 25 | class WlDisplay; 26 | class WlKeyboard; 27 | class WlRegistry; 28 | class WlSeat; 29 | class WlShm; 30 | class WlShmPool; 31 | class WlSurface; 32 | class XdgSurface; 33 | class XdgToplevel; 34 | class XdgWmBase; 35 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/keyboard.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "keyboard.hpp" 17 | #include "all.hpp" 18 | 19 | decltype(WlKeyboardSpec::listener) WlKeyboardSpec::listener { 20 | .keymap = &noHandler, 21 | .enter = &eventHandler<&WlKeyboard::onEnter>, 22 | .leave = &eventHandler<&WlKeyboard::onLeave>, 23 | .key = &noHandler, 24 | .modifiers = &noHandler, 25 | .repeat_info = &noHandler}; 26 | 27 | wl_keyboard* WlKeyboard::initKeyboard(const WlSeat& seat) { 28 | if (!seat.hasCapability(WL_SEAT_CAPABILITY_KEYBOARD)) { 29 | throw WlException("Seat ", seat.name(), " doesn't have Keyboard capabilities"); 30 | } 31 | 32 | return wl_seat_get_keyboard(seat.value()); 33 | } 34 | 35 | WlKeyboard::WlKeyboard(const WlSeat& seat) : WlObject {initKeyboard(seat)} {} 36 | 37 | WlKeyboard::WlKeyboard(const WlRegistry& registry) : WlKeyboard {registry.get()} {} 38 | 39 | bool WlKeyboard::hasFocus(wl_surface* surface) const { 40 | return m_focus.contains(surface); 41 | } 42 | 43 | bool WlKeyboard::hasFocus(const WlSurface& surface) const { 44 | return hasFocus(surface.value()); 45 | } 46 | 47 | std::uint32_t WlKeyboard::getFocusSerial(wl_surface* surface) const { 48 | return m_focus.at(surface); 49 | } 50 | 51 | std::uint32_t WlKeyboard::getFocusSerial(const WlSurface& surface) const { 52 | return getFocusSerial(surface.value()); 53 | } 54 | 55 | void WlKeyboard::onEnter(std::uint32_t serial, wl_surface* surface, wl_array*) { 56 | m_focus.insert_or_assign(surface, serial); 57 | } 58 | 59 | void WlKeyboard::onLeave(std::uint32_t serial, wl_surface* surface) { 60 | m_focus.erase(surface); 61 | } 62 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/keyboard.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | struct WlKeyboardSpec { 24 | WL_SPEC_BASE(wl_keyboard, 8) 25 | WL_SPEC_RELEASE(wl_keyboard) 26 | WL_SPEC_LISTENER(wl_keyboard) 27 | }; 28 | 29 | class WlKeyboard : public WlObject { 30 | friend WlKeyboardSpec; 31 | 32 | std::map m_focus {}; 33 | 34 | static wl_keyboard* initKeyboard(const WlSeat&); 35 | 36 | public: 37 | explicit WlKeyboard(const WlSeat&); 38 | explicit WlKeyboard(const WlRegistry&); 39 | 40 | bool hasFocus(wl_surface*) const; 41 | bool hasFocus(const WlSurface&) const; 42 | 43 | std::uint32_t getFocusSerial(wl_surface*) const; 44 | std::uint32_t getFocusSerial(const WlSurface&) const; 45 | 46 | private: 47 | void onEnter(std::uint32_t serial, wl_surface*, wl_array*); 48 | void onLeave(std::uint32_t serial, wl_surface*); 49 | }; 50 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/registry.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | #include 23 | 24 | struct WlRegistrySpec { 25 | WL_SPEC_BASE(wl_registry, 1) 26 | WL_SPEC_DESTROY(wl_registry) 27 | WL_SPEC_LISTENER(wl_registry) 28 | }; 29 | 30 | class WlRegistry : public WlObject { 31 | friend WlRegistrySpec; 32 | 33 | struct BoundObject { 34 | std::uint32_t name; 35 | std::string_view interface; 36 | std::shared_ptr object; 37 | }; 38 | 39 | const WlDisplay& m_display; 40 | std::map m_boundObjectsByName {}; 41 | std::multimap m_boundObjectsByInterface {}; 42 | 43 | template 44 | void bind(std::uint32_t name, std::uint32_t version); 45 | 46 | public: 47 | explicit WlRegistry(const WlDisplay& display); 48 | 49 | /** 50 | * Gets a C++-managed global Wayland object bound in this registry. 51 | * @tparam T Type of the Wayland object to get. 52 | * @throws WlException If there's no object of that type bound in the registry. 53 | */ 54 | template 55 | const T& get() const; 56 | 57 | private: 58 | void onGlobal(std::uint32_t name, const char* interface, std::uint32_t version); 59 | void onGlobalRemove(std::uint32_t name); 60 | }; 61 | 62 | template 63 | const T& WlRegistry::get() const { 64 | std::string_view name {T::spec_t::interface.name}; 65 | 66 | auto found = m_boundObjectsByInterface.find(name); 67 | if (found == m_boundObjectsByInterface.end()) { 68 | throw WlException("Tried to use global ", name, " but it wasn't bound by registry"); 69 | } 70 | 71 | return *std::static_pointer_cast(found->second.object); 72 | } 73 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/seat.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "seat.hpp" 17 | #include "all.hpp" 18 | 19 | wl_seat_listener WlSeatSpec::listener { 20 | .capabilities = &eventHandler<&WlSeat::onCapability>, 21 | .name = &eventHandler<&WlSeat::onName>, 22 | }; 23 | 24 | void WlSeat::onName(const char* name) { 25 | m_name = name; 26 | } 27 | 28 | void WlSeat::onCapability(std::uint32_t capabilities) { 29 | m_capabilities = static_cast(capabilities); 30 | } 31 | 32 | bool WlSeat::hasCapability(wl_seat_capability query) const { 33 | return (m_capabilities & query) != 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/seat.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | struct WlSeatSpec { 26 | WL_SPEC_BASE(wl_seat, 7) 27 | WL_SPEC_RELEASE(wl_seat) 28 | WL_SPEC_LISTENER(wl_seat) 29 | }; 30 | 31 | class WlSeat : public WlObject { 32 | friend WlSeatSpec; 33 | 34 | std::string m_name {"unnamed seat"}; 35 | wl_seat_capability m_capabilities {static_cast(0)}; 36 | 37 | public: 38 | explicit WlSeat(obj_t* value) : WlObject {value} {} 39 | 40 | [[nodiscard]] inline std::string_view name() const { return m_name; } 41 | [[nodiscard]] bool hasCapability(wl_seat_capability) const; 42 | 43 | private: 44 | void onName(const char*); 45 | void onCapability(std::uint32_t); 46 | }; 47 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/shm.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "shm.hpp" 17 | #include "all.hpp" 18 | 19 | wl_shm_listener WlShmSpec::listener { 20 | .format = &eventHandler<&WlShm::onFormat>, 21 | }; 22 | 23 | bool WlShm::supports(wl_shm_format format) const { 24 | return m_formats.contains(format); 25 | } 26 | 27 | void WlShm::onFormat(std::uint32_t format) { 28 | m_formats.insert(wl_shm_format(format)); 29 | } 30 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/shm.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | struct WlShmSpec { 24 | WL_SPEC_BASE(wl_shm, 1) 25 | WL_SPEC_DESTROY(wl_shm) 26 | WL_SPEC_LISTENER(wl_shm) 27 | }; 28 | 29 | class WlShm : public WlObject { 30 | friend WlShmSpec; 31 | 32 | std::set m_formats {}; 33 | 34 | public: 35 | explicit WlShm(obj_t* value) : WlObject {value} {} 36 | [[nodiscard]] bool supports(wl_shm_format) const; 37 | 38 | private: 39 | void onFormat(std::uint32_t); 40 | }; 41 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/shm_pool.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "shm_pool.hpp" 17 | #include "all.hpp" 18 | 19 | WlShmPool::WlShmPool(const WlShm& shm, Fd&& fd, std::int32_t size) : WlObject {wl_shm_create_pool(shm.value(), fd.value(), size)}, m_fd {std::move(fd)}, m_size(size) {} 20 | 21 | std::unique_ptr WlShmPool::fromMemfd(const WlShm& shm, std::int32_t size) { 22 | return std::make_unique(shm, Fd::memfd(size), size); 23 | } 24 | 25 | std::unique_ptr WlShmPool::fromMemfd(const WlRegistry& registry, std::int32_t size) { 26 | return fromMemfd(registry.get(), size); 27 | } 28 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/shm_pool.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "../fd.hpp" 19 | #include "forward.hpp" 20 | #include "spec.hpp" 21 | 22 | struct WlShmPoolSpec { 23 | WL_SPEC_BASE(wl_shm_pool, 1) 24 | WL_SPEC_DESTROY(wl_shm_pool) 25 | }; 26 | 27 | class WlShmPool : public WlObject { 28 | Fd m_fd; 29 | std::int32_t m_size; 30 | 31 | public: 32 | explicit WlShmPool(const WlShm&, Fd&&, std::int32_t size); 33 | 34 | static std::unique_ptr fromMemfd(const WlShm&, std::int32_t size); 35 | static std::unique_ptr fromMemfd(const WlRegistry&, std::int32_t size); 36 | }; 37 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/surface.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "surface.hpp" 17 | #include "all.hpp" 18 | 19 | WlSurface::WlSurface(const WlCompositor& compositor, const XdgWmBase& xdgWmBase) 20 | : WlObject {wl_compositor_create_surface(compositor.value())} 21 | , m_xdg {std::make_unique(xdgWmBase, *this)} {} 22 | 23 | WlSurface::WlSurface(const WlRegistry& registry) : WlSurface {registry.get(), registry.get()} {} 24 | 25 | void WlSurface::attach(std::unique_ptr&& buffer) { 26 | m_buffer = std::move(buffer); 27 | wl_surface_attach(value(), getValue(m_buffer), 0, 0); // 0, 0 required by protocol 28 | } 29 | 30 | void WlSurface::damage(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) const { 31 | wl_surface_damage(value(), x, y, width, height); 32 | } 33 | 34 | void WlSurface::commit() const { 35 | wl_surface_commit(value()); 36 | } 37 | 38 | void WlSurface::setTitle(const char* title) const { 39 | m_xdg->setTitle(title); 40 | } 41 | 42 | void WlSurface::scheduleAttach(std::unique_ptr&& buffer) { 43 | m_xdg->scheduleAttach(std::move(buffer)); 44 | } 45 | 46 | void WlSurface::scheduleDamage(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { 47 | m_xdg->scheduleDamage(x, y, w, h); 48 | } 49 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/surface.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | struct WlSurfaceSpec { 22 | WL_SPEC_BASE(wl_surface, 5) 23 | WL_SPEC_DESTROY(wl_surface) 24 | }; 25 | 26 | class WlSurface : public WlObject { 27 | std::unique_ptr m_buffer; 28 | std::unique_ptr m_xdg; 29 | 30 | public: 31 | explicit WlSurface(const WlCompositor&, const XdgWmBase&); 32 | explicit WlSurface(const WlRegistry&); 33 | 34 | void attach(std::unique_ptr&&); 35 | void damage(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) const; 36 | void commit() const; 37 | 38 | void setTitle(const char*) const; 39 | void scheduleAttach(std::unique_ptr&&); 40 | void scheduleDamage(uint32_t x, uint32_t y, uint32_t w, uint32_t h); 41 | }; 42 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_surface.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "xdg_surface.hpp" 17 | #include "all.hpp" 18 | 19 | xdg_surface_listener XdgSurfaceSpec::listener {.configure = &eventHandler<&XdgSurface::configure>}; 20 | 21 | XdgSurface::XdgSurface(const XdgWmBase& base, WlSurface& surface) 22 | : WlObject {xdg_wm_base_get_xdg_surface(base.value(), surface.value())} 23 | , m_surface {surface} 24 | , m_toplevel {std::make_unique(*this)} {} 25 | 26 | void XdgSurface::configure(std::uint32_t serial) { 27 | auto didAction = false; 28 | 29 | if (m_pendingBuffer) { 30 | m_surface.attach(std::move(m_pendingBuffer)); 31 | didAction = true; 32 | } 33 | 34 | if (m_pendingDamage) { 35 | auto args = m_pendingDamage.value(); 36 | m_surface.damage(std::get<0>(args), std::get<1>(args), std::get<2>(args), std::get<3>(args)); 37 | m_pendingDamage.reset(); 38 | didAction = true; 39 | } 40 | 41 | xdg_surface_ack_configure(value(), serial); 42 | 43 | if (didAction) { 44 | m_surface.commit(); 45 | } 46 | } 47 | 48 | void XdgSurface::setTitle(const char* title) const { 49 | m_toplevel->setTitle(title); 50 | } 51 | 52 | void XdgSurface::scheduleAttach(std::unique_ptr&& buffer) { 53 | m_pendingBuffer = std::move(buffer); 54 | } 55 | 56 | void XdgSurface::scheduleDamage(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { 57 | m_pendingDamage = {x, y, w, h}; 58 | } 59 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_surface.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | 21 | #include 22 | 23 | #include 24 | 25 | struct XdgSurfaceSpec { 26 | WL_SPEC_BASE(xdg_surface, 5) 27 | WL_SPEC_DESTROY(xdg_surface) 28 | WL_SPEC_LISTENER(xdg_surface) 29 | }; 30 | 31 | class XdgSurface : public WlObject { 32 | friend XdgSurfaceSpec; 33 | 34 | WlSurface& m_surface; 35 | std::unique_ptr m_toplevel; 36 | std::unique_ptr m_pendingBuffer {}; 37 | std::optional> m_pendingDamage {}; 38 | 39 | public: 40 | explicit XdgSurface(const XdgWmBase&, WlSurface&); 41 | 42 | void setTitle(const char*) const; 43 | void scheduleAttach(std::unique_ptr&&); 44 | void scheduleDamage(uint32_t x, uint32_t y, uint32_t w, uint32_t h); 45 | 46 | private: 47 | void configure(std::uint32_t); 48 | }; 49 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_toplevel.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "xdg_toplevel.hpp" 17 | #include "all.hpp" 18 | 19 | XdgToplevel::XdgToplevel(const XdgSurface& surface) : WlObject {xdg_surface_get_toplevel(surface.value())} {} 20 | 21 | void XdgToplevel::setTitle(const char* title) const { 22 | xdg_toplevel_set_title(value(), title); 23 | } 24 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_toplevel.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | #include 21 | 22 | struct XdgToplevelSpec { 23 | WL_SPEC_BASE(xdg_toplevel, 4) 24 | WL_SPEC_DESTROY(xdg_toplevel) 25 | }; 26 | 27 | class XdgToplevel : public WlObject { 28 | public: 29 | explicit XdgToplevel(const XdgSurface&); 30 | 31 | void setTitle(const char*) const; 32 | }; 33 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_wm_base.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include "xdg_wm_base.hpp" 17 | 18 | xdg_wm_base_listener XdgWmBaseSpec::listener {.ping = &eventHandler<&XdgWmBase::ping>}; 19 | 20 | void XdgWmBase::ping(std::uint32_t serial) { 21 | xdg_wm_base_pong(value(), serial); 22 | } 23 | -------------------------------------------------------------------------------- /src/cbwayland/src/objects/xdg_wm_base.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include "forward.hpp" 19 | #include "spec.hpp" 20 | #include 21 | 22 | struct XdgWmBaseSpec { 23 | WL_SPEC_BASE(xdg_wm_base, 4) 24 | WL_SPEC_DESTROY(xdg_wm_base) 25 | WL_SPEC_LISTENER(xdg_wm_base) 26 | }; 27 | 28 | class XdgWmBase : public WlObject { 29 | friend XdgWmBaseSpec; 30 | 31 | public: 32 | explicit XdgWmBase(obj_t* value) : WlObject {value} {} 33 | 34 | private: 35 | void ping(std::uint32_t); 36 | }; 37 | -------------------------------------------------------------------------------- /src/cbx11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(cbx11 MODULE 2 | src/x11.cpp 3 | ) 4 | 5 | target_link_libraries(cbx11 6 | ${X11_LIBRARIES} 7 | gui 8 | ) 9 | 10 | enable_lto(cbx11) 11 | 12 | target_include_directories(cbx11 PRIVATE ${X11_INCLUDE_DIR}) 13 | 14 | install(TARGETS cbx11 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 15 | -------------------------------------------------------------------------------- /src/clang-format-check.ps1: -------------------------------------------------------------------------------- 1 | clang-format-15 --Werror -i --verbose --dry-run (Get-ChildItem -Recurse -Include *.cpp,*.hpp) 2 | -------------------------------------------------------------------------------- /src/clang-format-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | find \ 5 | '(' \ 6 | -name '*.cpp' \ 7 | -o -name '*.hpp' \ 8 | ')' \ 9 | -exec \ 10 | clang-format-15 --Werror -i --verbose --dry-run '{}' + 11 | -------------------------------------------------------------------------------- /src/clang-format.ps1: -------------------------------------------------------------------------------- 1 | clang-format-15 --Werror -i --verbose (Get-ChildItem -Recurse -Include *.cpp,*.hpp) 2 | -------------------------------------------------------------------------------- /src/clang-format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | find \ 5 | '(' \ 6 | -name '*.cpp' \ 7 | -o -name '*.hpp' \ 8 | ')' \ 9 | -exec \ 10 | clang-format-15 --Werror -i --verbose '{}' + 11 | -------------------------------------------------------------------------------- /src/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(gui STATIC 2 | src/fork.cpp 3 | src/gui.cpp 4 | src/utils.cpp 5 | src/infermime.cpp 6 | src/inferextension.cpp 7 | ) 8 | target_include_directories(gui PUBLIC include/all) 9 | set_property(TARGET gui PROPERTY POSITION_INDEPENDENT_CODE ON) 10 | 11 | include(CheckSymbolExists) 12 | check_symbol_exists(fork "unistd.h" HAVE_FORK) 13 | if(HAVE_FORK) 14 | target_compile_definitions(gui PUBLIC HAVE_FORK) 15 | endif() 16 | 17 | if(X11WL) 18 | target_sources(gui PRIVATE 19 | src/x11wl/mime.cpp 20 | ) 21 | 22 | target_include_directories(gui PUBLIC include/x11wl) 23 | endif() 24 | 25 | -------------------------------------------------------------------------------- /src/gui/include/all/clipboard/logging.hpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #pragma once 17 | 18 | #include 19 | #include 20 | 21 | #if defined(NDEBUG) 22 | class NullBuffer : public std::streambuf { 23 | public: 24 | int overflow(int c) override { return c; } 25 | }; 26 | 27 | static NullBuffer nullBuffer; 28 | static std::ostream nullStream(&nullBuffer); 29 | static std::ostream& debugStream = nullStream; 30 | #else 31 | static std::ostream& debugStream = std::cerr; 32 | #endif 33 | -------------------------------------------------------------------------------- /src/gui/src/fork.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include 17 | 18 | void Forker::atFork(Forker::callback_t&& callback) { 19 | m_forkCallbacks.emplace_back(std::move(callback)); 20 | } 21 | 22 | void Forker::atNonFork(Forker::callback_t&& callback) { 23 | m_nonForkCallbacks.emplace_back(std::move(callback)); 24 | } 25 | 26 | #if defined(HAVE_FORK) 27 | bool waitForSuccessSignal() { 28 | sigset_t sigset; 29 | sigemptyset(&sigset); 30 | sigaddset(&sigset, SIGUSR1); 31 | sigaddset(&sigset, SIGUSR2); 32 | sigprocmask(SIG_BLOCK, &sigset, nullptr); 33 | int sig; 34 | sigwait(&sigset, &sig); 35 | return sig == SIGUSR1; 36 | } 37 | #endif -------------------------------------------------------------------------------- /src/gui/src/gui.cpp: -------------------------------------------------------------------------------- 1 | /* The Clipboard Project - Cut, copy, and paste anything, anytime, anywhere, all from the terminal. 2 | Copyright (C) 2023 Jackson Huff and other contributors on GitHub.com 3 | SPDX-License-Identifier: GPL-3.0-or-later 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see .*/ 16 | #include 17 | 18 | std::ostream& operator<<(std::ostream& stream, const ClipboardPathsAction& action) { 19 | if (action == ClipboardPathsAction::Copy) { 20 | stream << "copy"; 21 | } else if (action == ClipboardPathsAction::Cut) { 22 | stream << "cut"; 23 | } else { 24 | stream << "unknown"; 25 | } 26 | 27 | return stream; 28 | } 29 | 30 | ClipboardPaths::ClipboardPaths(std::vector&& paths, ClipboardPathsAction action) : m_action(action), m_paths(std::move(paths)) {} 31 | 32 | ClipboardPaths::ClipboardPaths(const std::vector& paths, ClipboardPathsAction action) : m_action(action), m_paths(paths) {} 33 | 34 | ClipboardContent::ClipboardContent(const std::string& text, const std::string& mime) : m_type(ClipboardContentType::Text), mime_type(mime), m_data(text) {} 35 | 36 | ClipboardContent::ClipboardContent(std::string&& text, const std::string& mime) : m_type(ClipboardContentType::Text), mime_type(mime), m_data(std::move(text)) {} 37 | 38 | ClipboardContent::ClipboardContent(const ClipboardPaths& paths) : m_type(ClipboardContentType::Paths), mime_type("text/uri-list"), m_data(paths) {} 39 | 40 | ClipboardContent::ClipboardContent(ClipboardPaths&& paths) : m_type(ClipboardContentType::Paths), mime_type("text/uri-list"), m_data(std::move(paths)) {} 41 | 42 | ClipboardContent::ClipboardContent(std::vector&& paths, ClipboardPathsAction action) : ClipboardContent(ClipboardPaths(std::move(paths), action)) {} 43 | 44 | ClipboardContent::ClipboardContent(const std::vector& paths, ClipboardPathsAction action) : ClipboardContent(ClipboardPaths(paths, action)) {} 45 | 46 | ClipboardContent::ClipboardContent() : m_type(ClipboardContentType::Empty), m_data(nullptr) {} 47 | -------------------------------------------------------------------------------- /src/shellcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | shellcheck -e SC1091 -e SC2012 src/tests/*.sh ./*.sh -------------------------------------------------------------------------------- /src/tests/Exosphere 2.0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/tests/Exosphere 2.0.mp3 -------------------------------------------------------------------------------- /src/tests/TurnYourClipboardUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Slackadays/Clipboard/f24d6cd5f33693e5cad155a2e3dafd9ebb6767ad/src/tests/TurnYourClipboardUp.png -------------------------------------------------------------------------------- /src/tests/add-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Add files" 5 | 6 | make_files 7 | 8 | echo "Foobar" > dummyfile 9 | 10 | cb copy dummyfile 11 | 12 | cb add testfile testdir 13 | 14 | item_is_in_cb 0 testfile 15 | 16 | item_is_in_cb 0 testdir/testfile 17 | 18 | echo "Foobar" > addedfile 19 | 20 | cb add addedfile 21 | 22 | item_is_in_cb 0 addedfile 23 | 24 | mkdir addeddir 25 | 26 | echo "Foobar" > addeddir/addedfile 27 | 28 | cb add addeddir 29 | 30 | item_is_in_cb 0 addeddir/addedfile 31 | 32 | assert_fails cb add foo bar baz 33 | 34 | assert_fails cb add "Some text" 35 | 36 | echo "Some text" | assert_fails cb add -------------------------------------------------------------------------------- /src/tests/add-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Add piped data" 4 | 5 | printf "Foobar" | cb 6 | 7 | printf "Foobar" | cb add 8 | 9 | assert_equals "FoobarFoobar" "$(cb paste)" # add paste to work around gha bug 10 | 11 | cb add foo bar baz -------------------------------------------------------------------------------- /src/tests/add-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Add text" 5 | 6 | cb copy "Foobar" 7 | 8 | cb add "Baz" 9 | 10 | unset CLIPBOARD_FORCETTY 11 | 12 | assert_equals "FoobarBaz" "$(cb paste)" 13 | 14 | touch foofile 15 | 16 | assert_fails cb add foofile bar baz -------------------------------------------------------------------------------- /src/tests/bad-action.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Give a junk action" 4 | export CLIPBOARD_FORCETTY=1 5 | 6 | assert_fails cb FoobarActionThatDoesNotExist -------------------------------------------------------------------------------- /src/tests/clear-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export CLIPBOARD_FORCETTY=1 3 | . ./resources.sh 4 | start_test "Clear files" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | item_is_in_cb 0 testfile 11 | 12 | item_is_in_cb 0 testdir/testfile 13 | 14 | cb clear 15 | 16 | item_is_not_in_cb 0 testfile 17 | 18 | item_is_not_in_cb 0 testdir/testfile -------------------------------------------------------------------------------- /src/tests/clear-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Clear piped data" 4 | 5 | echo "Foobar" | cb 6 | 7 | item_is_in_cb 0 rawdata.clipboard 8 | 9 | export CLIPBOARD_FORCETTY=1 10 | 11 | cb clear 12 | 13 | item_is_not_in_cb 0 rawdata.clipboard -------------------------------------------------------------------------------- /src/tests/clear-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Clear user provided text" 5 | 6 | cb copy "Foobar" 7 | 8 | item_is_in_cb 0 rawdata.clipboard 9 | 10 | cb clear 11 | 12 | item_is_not_in_cb 0 rawdata.clipboard -------------------------------------------------------------------------------- /src/tests/copy-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export CLIPBOARD_FORCETTY=1 3 | . ./resources.sh 4 | start_test "Copy files" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | item_is_in_cb 0 testfile 11 | 12 | item_is_in_cb 0 testdir/testfile 13 | 14 | mkdir dir1 15 | 16 | mkdir dir2 17 | 18 | cb copy dir1 dir2 19 | 20 | item_is_in_cb 0 dir1 21 | 22 | item_is_in_cb 0 dir2 23 | 24 | echo "Foobar" > file1 25 | 26 | echo "Foobar" > file2 27 | 28 | cb copy file1 dir1 dir2 29 | 30 | item_is_in_cb 0 file1 31 | 32 | item_is_in_cb 0 dir1 33 | 34 | item_is_in_cb 0 dir2 35 | 36 | cb copy file1 file2 dir1 37 | 38 | item_is_in_cb 0 file1 39 | 40 | item_is_in_cb 0 file2 41 | 42 | item_is_in_cb 0 dir1 43 | 44 | cb copy file1 file2 dir1 dir2 45 | 46 | item_is_in_cb 0 file1 47 | 48 | item_is_in_cb 0 file2 49 | 50 | item_is_in_cb 0 dir1 51 | 52 | item_is_in_cb 0 dir2 53 | 54 | cb copy ../TurnYourClipboardUp.png 55 | 56 | cb paste 57 | 58 | items_match TurnYourClipboardUp.png ../TurnYourClipboardUp.png 59 | 60 | cb clear 61 | 62 | rm -f TurnYourClipboardUp.png 63 | 64 | cb --fast-copy copy testfile testdir 65 | 66 | item_is_in_cb 0 testfile 67 | 68 | item_is_in_cb 0 testdir/testfile 69 | 70 | cb --fast-copy copy ../TurnYourClipboardUp.png 71 | 72 | cb --fast-copy paste 73 | 74 | items_match TurnYourClipboardUp.png ../TurnYourClipboardUp.png 75 | 76 | assert_fails cb copy testfile foo bar baz -------------------------------------------------------------------------------- /src/tests/copy-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Copy piped data" 4 | 5 | echo "Foobar" | cb 6 | 7 | item_is_in_cb 0 rawdata.clipboard 8 | 9 | export CLIPBOARD_FORCETTY=1 10 | 11 | cb paste 12 | 13 | item_exists clipboard0-0.txt 14 | 15 | unset CLIPBOARD_FORCETTY 16 | 17 | cb < ../TurnYourClipboardUp.png 18 | 19 | cb paste > temp # work around github actions tty bug 20 | 21 | items_match temp ../TurnYourClipboardUp.png -------------------------------------------------------------------------------- /src/tests/copy-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Copy user provided text" 5 | 6 | cb copy "Foobar" 7 | 8 | item_is_in_cb 0 rawdata.clipboard -------------------------------------------------------------------------------- /src/tests/cut-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Cut files" 5 | 6 | make_files 7 | 8 | cb cut testfile testdir 9 | 10 | setup_dir pastehere 11 | 12 | cb paste 13 | 14 | cd ../ 15 | 16 | item_is_not_here testfile 17 | 18 | item_is_not_here testdir/testfile -------------------------------------------------------------------------------- /src/tests/cut-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Cut piped data" 4 | 5 | echo "Foobar" | cb cut 6 | 7 | item_is_in_cb 0 rawdata.clipboard 8 | 9 | export CLIPBOARD_FORCETTY=1 10 | 11 | cb paste 12 | 13 | item_exists clipboard0-0.txt 14 | 15 | item_is_not_in_cb 0 rawdata.clipboard -------------------------------------------------------------------------------- /src/tests/cut-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Cut user provided text" 5 | 6 | cb cut "Foobar" 7 | 8 | item_is_in_cb 0 rawdata.clipboard 9 | 10 | cb paste 11 | 12 | item_exists clipboard0-0.txt 13 | 14 | item_is_not_in_cb 0 rawdata.clipboard -------------------------------------------------------------------------------- /src/tests/edit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Do Edit action" 4 | 5 | cb edit -------------------------------------------------------------------------------- /src/tests/export.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Export clipboards" 4 | 5 | export CLIPBOARD_FORCETTY=1 6 | 7 | cb copy "Some text" 8 | 9 | entryfor0="$(get_current_entry_name 0)" 10 | 11 | unset CLIPBOARD_FORCETTY 12 | 13 | cb copy2 < ../TurnYourClipboardUp.png 14 | 15 | entryfor2="$(get_current_entry_name 2)" 16 | 17 | cb copy3 < ../"Exosphere 2.0.mp3" 18 | 19 | entryfor3="$(get_current_entry_name 3)" 20 | 21 | export CLIPBOARD_FORCETTY=1 22 | 23 | make_files 24 | 25 | cb copy4 testfile testdir 26 | 27 | entryfor4="$(get_current_entry_name 4)" 28 | 29 | message="$(cb export 2>&1)" 30 | 31 | content_is_shown "$message" "4" 32 | 33 | item_exists Exported_Clipboards/0/data/"$entryfor0"/rawdata.clipboard "Some text" 34 | 35 | item_exists Exported_Clipboards/2/data/"$entryfor2"/rawdata.clipboard "$(cat ../TurnYourClipboardUp.png)" 36 | 37 | item_exists Exported_Clipboards/3/data/"$entryfor3"/rawdata.clipboard "$(cat ../"Exosphere 2.0.mp3")" 38 | 39 | item_exists Exported_Clipboards/4/data/"$entryfor4"/testfile 40 | 41 | item_exists Exported_Clipboards/4/data/"$entryfor4"/testdir/testfile -------------------------------------------------------------------------------- /src/tests/help.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Show help message" 5 | 6 | output="$(cb help)" 7 | 8 | content_is_shown "$output" "cb" 9 | 10 | output="$(cb -h)" 11 | 12 | content_is_shown "$output" "cb" 13 | 14 | output="$(cb --help)" 15 | 16 | content_is_shown "$output" "cb" 17 | 18 | cb --bachata -------------------------------------------------------------------------------- /src/tests/history.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Show history" 4 | 5 | export CLIPBOARD_FORCETTY=1 6 | 7 | cb copy "Some text 1" 8 | 9 | cb copy "Some text 2" 10 | 11 | cb copy "Some text 3" 12 | 13 | cb copy "Some text 4" 14 | 15 | cb copy "Some text 5" 16 | 17 | if [ "$(uname)" = "Darwin" ] || [ "$(uname)" = "FreeBSD" ] || [ "$(uname)" = "OpenBSD" ] || [ "$(uname)" = "NetBSD" ] 18 | then 19 | echo "⏭️ Skipping test on BSD platform due to AIO redirection bug" 20 | exit 0 21 | fi 22 | 23 | message="$(cb history 2>&1)" 24 | 25 | content_is_shown "$message" "Some text 1" 26 | 27 | content_is_shown "$message" "Some text 2" 28 | 29 | content_is_shown "$message" "Some text 3" 30 | 31 | content_is_shown "$message" "Some text 4" 32 | 33 | content_is_shown "$message" "Some text 5" 34 | 35 | unset CLIPBOARD_FORCETTY 36 | 37 | json="$(cb history 2>&1)" 38 | 39 | content_is_shown "$json" '"content": "Some text 1"' 40 | 41 | content_is_shown "$json" '"content": "Some text 2"' 42 | 43 | content_is_shown "$json" '"content": "Some text 3"' 44 | 45 | content_is_shown "$json" '"content": "Some text 4"' 46 | 47 | content_is_shown "$json" '"content": "Some text 5"' -------------------------------------------------------------------------------- /src/tests/ignore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Ignore regex patterns" 4 | 5 | export CLIPBOARD_FORCETTY=1 6 | 7 | cb ignore "" 8 | 9 | make_files 10 | 11 | cb copy testfile testdir 12 | 13 | item_is_in_cb 0 "testfile" 14 | 15 | item_is_in_cb 0 "testdir" 16 | 17 | cb ignore "testfile" 18 | 19 | item_is_in_cb 0 "testdir" 20 | 21 | item_is_not_in_cb 0 "testfile" 22 | 23 | cb ignore "testdir" 24 | 25 | item_is_not_in_cb 0 "testdir" 26 | 27 | cb ignore "" -------------------------------------------------------------------------------- /src/tests/languages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Show CB languages" 5 | 6 | make_files 7 | 8 | CLIPBOARD_LOCALE=en_US.UTF-8 cb copy testfile testdir 9 | 10 | CLIPBOARD_LOCALE=es_ES.UTF-8 cb copiar testfile testdir 11 | 12 | CLIPBOARD_LOCALE=pt_BR.UTF-8 cb copiar testfile testdir 13 | 14 | CLIPBOARD_LOCALE=tr_TR.UTF-8 cb kopyala testfile testdir -------------------------------------------------------------------------------- /src/tests/note-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Note piped in text" 4 | 5 | echo "Foobar" | cb note 6 | 7 | # check CI is true and the runner is macOS 8 | set +u 9 | if [ "$CI" = "true" ] && [ "$(uname)" != "Linux" ] 10 | then 11 | echo "⏭️ Skipping test on macOS CI due to Not A TTY bug" 12 | exit 0 13 | fi 14 | 15 | assert_equals "Foobar" "$(cb note)" 16 | 17 | echo "" | cb note 18 | 19 | assert_equals "" "$(cb note)" -------------------------------------------------------------------------------- /src/tests/note-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Note user provided text" 4 | export CLIPBOARD_FORCETTY=1 5 | 6 | cb note "Foobar" 7 | 8 | unset CLIPBOARD_FORCETTY 9 | 10 | #skip anything in CI if it isn't Linux 11 | set +u 12 | if [ "$CI" = "true" ] && [ "$(uname)" != "Linux" ] 13 | then 14 | echo "⏭️ Skipping test on macOS CI due to Not A TTY bug" 15 | exit 0 16 | fi 17 | 18 | assert_equals "Foobar" "$(cb note)" 19 | 20 | content_is_shown "$(CLIPBOARD_FORCETTY=1 cb note)" "Foobar" 21 | 22 | cb note "" 23 | 24 | assert_equals "" "$(cb note)" 25 | 26 | cb note "Foobar" "Baz" 27 | 28 | assert_equals "Foobar Baz" "$(cb note)" -------------------------------------------------------------------------------- /src/tests/paste-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Paste files" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | setup_dir pastehere 11 | 12 | cb paste 13 | 14 | item_exists testfile 15 | 16 | item_exists testdir/testfile 17 | 18 | cb clear 19 | 20 | cb paste -------------------------------------------------------------------------------- /src/tests/paste-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Paste piped data" 4 | 5 | echo "Foobar" | cb 6 | 7 | export CLIPBOARD_FORCETTY=1 8 | 9 | cb paste 10 | 11 | item_exists clipboard0-0.txt -------------------------------------------------------------------------------- /src/tests/paste-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Paste user provided text" 5 | 6 | cb copy "Foobar" 7 | 8 | cb paste 9 | 10 | item_exists clipboard0-0.txt -------------------------------------------------------------------------------- /src/tests/remove-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Remove files" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | item_is_in_cb 0 testfile 11 | 12 | item_is_in_cb 0 testdir/testfile 13 | 14 | cb remove testfile 15 | 16 | item_is_not_in_cb 0 testfile 17 | 18 | cb remove testdir 19 | 20 | item_is_not_in_cb 0 testdir/testfile 21 | 22 | cb copy testfile testdir 23 | 24 | cb remove "test.*" 25 | 26 | item_is_not_in_cb 0 testfile 27 | 28 | item_is_not_in_cb 0 testdir/testfile 29 | 30 | cb copy testfile testdir 31 | 32 | cb remove "testfile" "testdir" 33 | 34 | item_is_not_in_cb 0 testfile 35 | 36 | item_is_not_in_cb 0 testdir/testfile 37 | 38 | cb copy testfile testdir 39 | 40 | cb remove ".*file" ".*dir" 41 | 42 | item_is_not_in_cb 0 testfile 43 | 44 | item_is_not_in_cb 0 testdir/testfile 45 | 46 | assert_fails cb remove "foo.*" 47 | 48 | assert_fails cb remove ".*bar" 49 | 50 | assert_fails cb remove "baz" 51 | 52 | assert_fails cb remove foo bar baz -------------------------------------------------------------------------------- /src/tests/remove-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Remove piped data" 4 | 5 | echo "Foobar" | cb copy 6 | 7 | item_is_in_cb 0 rawdata.clipboard 8 | 9 | echo "Baz" | assert_fails cb remove 10 | 11 | echo "Foobar" | cb remove 12 | 13 | assert_equals "" "$(cb paste)" -------------------------------------------------------------------------------- /src/tests/remove-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Remove text" 4 | export CLIPBOARD_FORCETTY=1 5 | 6 | cb copy "Foobar" 7 | 8 | item_is_in_cb 0 rawdata.clipboard 9 | 10 | cb remove "Foobar" 11 | 12 | unset CLIPBOARD_FORCETTY 13 | 14 | assert_equals "" "$(cb paste)" -------------------------------------------------------------------------------- /src/tests/resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | testname="(Unknown)" 5 | 6 | make_files() { 7 | echo "Foobar" > testfile 8 | mkdir testdir 9 | echo "Foobar" > testdir/testfile 10 | } 11 | 12 | setup_dir() { 13 | mkdir test_"$1" 14 | cd test_"$1" 15 | } 16 | 17 | pass_test() { 18 | if [ "$?" -eq "0" ] 19 | then 20 | printf "🎉 \033[1m%s\033[0m passed\n" "$testname" 21 | else 22 | printf "💥 \033[1m%s\033[0m failed\n" "$testname" 23 | fi 24 | } 25 | 26 | start_test() { 27 | export testname="$1" 28 | cols=$(tput cols 2>/dev/null || echo 80) 29 | i=0 30 | while [ $i -lt "$cols" ]; do printf "━"; i=$((i+1)); done 31 | printf "🏁 Starting \033[1m%s\033[0m (file \033[1m%s\033[0m)\n" "$testname" "$0" 32 | setup_dir "${0%.sh}" 33 | trap pass_test 0 34 | } 35 | 36 | fail() { 37 | printf "%s\n" "$1" 38 | exit 1 39 | } 40 | 41 | assert_equals() { 42 | if [ "$1" = "$2" ] 43 | then 44 | return 0 45 | else 46 | truncated1=$(printf "%s" "$1" | head -c 64) 47 | truncated2=$(printf "%s" "$2" | head -c 64) 48 | fail "😕 $truncated1 doesn't equal $truncated2" 49 | fi 50 | } 51 | 52 | assert_fails() { 53 | echo "⏩ The following should fail:" 54 | if "$@" 55 | then 56 | fail "😕 This command didn't fail" 57 | else 58 | return 0 59 | fi 60 | } 61 | 62 | verify_contents() { 63 | contents=$(cat "$1") 64 | baseline="$2" 65 | if [ "$contents" != "$baseline" ] 66 | then 67 | fail "😕 The contents don't match: $contents" 68 | fi 69 | } 70 | 71 | content_is_shown() { 72 | if printf "%s" "$1" | grep -q "$2" 73 | then 74 | return 0 75 | else 76 | fail "😕 The content $2 isn't shown" 77 | fi 78 | } 79 | 80 | get_current_entry_name() { 81 | # Get the highest numbered entry folder, where 10 is the entry name in /tmp/Clipboard/0/data/10 82 | ls "$CLIPBOARD_TMPDIR"/Clipboard/"$1"/data/ | sort -n | tail -n 1 83 | } 84 | 85 | item_is_in_cb() { 86 | clipboard="$1" 87 | item="$2" 88 | entry="$(get_current_entry_name "$clipboard")" 89 | if [ -f "$CLIPBOARD_TMPDIR"/Clipboard/"$clipboard"/data/"$entry"/"$item" ] 90 | then 91 | verify_contents "$CLIPBOARD_TMPDIR"/Clipboard/"$clipboard"/data/"$entry"/"$item" "Foobar" 92 | return 0 93 | elif [ -d "$CLIPBOARD_TMPDIR"/Clipboard/"$clipboard"/data/"$entry"/"$item" ] 94 | then 95 | return 0 96 | else 97 | fail "😕 The item $item doesn't exist in clipboard $clipboard" 98 | fi 99 | } 100 | 101 | item_exists() { 102 | item="$1" 103 | content="${2:-Foobar}" 104 | if [ -f "$item" ] || [ -d "$item" ] 105 | then 106 | verify_contents "$item" "$content" 107 | return 0 108 | else 109 | fail "😕 The item $item doesn't exist here" 110 | fi 111 | } 112 | 113 | item_is_not_here() { 114 | item="$1" 115 | if [ -f "$item" ] 116 | then 117 | fail "😕 The item $item exists here" 118 | else 119 | return 0 120 | fi 121 | } 122 | 123 | item_is_not_in_cb() { 124 | clipboard="$1" 125 | item="$2" 126 | entry="$(get_current_entry_name "$clipboard")" 127 | if [ -f "$CLIPBOARD_TMPDIR"/Clipboard/"$clipboard"/data/"$entry"/"$item" ] 128 | then 129 | fail "😕 The item $item exists in clipboard $clipboard" 130 | else 131 | return 0 132 | fi 133 | } 134 | 135 | items_match() { 136 | #use diff to compare the contents of the files 137 | if diff "$1" "$2" 138 | then 139 | return 0 140 | else 141 | fail "😕 The files don't match" 142 | fi 143 | } -------------------------------------------------------------------------------- /src/tests/show-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Show file clipboard content" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | output="$(cb show 2>&1)" 11 | 12 | content_is_shown "$output" testfile 13 | 14 | content_is_shown "$output" testdir -------------------------------------------------------------------------------- /src/tests/show-pipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Show piped data" 4 | 5 | echo "Foobar" | cb 6 | 7 | export CLIPBOARD_FORCETTY=1 8 | 9 | output=$(cb show 2>&1) 10 | 11 | item_is_in_cb 0 rawdata.clipboard 12 | 13 | content_is_shown "$output" "Foobar" -------------------------------------------------------------------------------- /src/tests/show-text.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Show user provided text" 5 | 6 | cb copy "Foobar" 7 | 8 | item_is_in_cb 0 rawdata.clipboard 9 | 10 | output=$(cb show 2>&1) 11 | 12 | content_is_shown "$output" "Foobar" -------------------------------------------------------------------------------- /src/tests/status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | export CLIPBOARD_FORCETTY=1 4 | start_test "Show clipboard status" 5 | 6 | make_files 7 | 8 | cb copy testfile testdir 9 | 10 | # check CI is true and the runner is not Linux 11 | set +u 12 | if [ "$CI" = "true" ] && [ "$(uname)" != "Linux" ] 13 | then 14 | echo "⏭️ Skipping test on this platform CI due to Not A TTY bug" 15 | exit 0 16 | fi 17 | 18 | content="$(cb 2>&1)" 19 | 20 | content_is_shown "$content" "testfile" 21 | 22 | content_is_shown "$content" "testdir" 23 | 24 | content_is_shown "$content" "0" 25 | 26 | content="$(cb status 2>&1)" 27 | 28 | content_is_shown "$content" "testfile" 29 | 30 | content_is_shown "$content" "testdir" 31 | 32 | content_is_shown "$content" "0" -------------------------------------------------------------------------------- /src/tests/suite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | clear_tempdirs() { 5 | rm -rf test_* 6 | } 7 | 8 | trap clear_tempdirs 0 9 | 10 | if [ -z "${CLIPBOARD_TMPDIR:-}" ] 11 | then 12 | printf "\033[1mEnter CB's temp directory (no slash at end):\033[0m " 13 | read -r CLIPBOARD_TMPDIR 14 | export CLIPBOARD_TMPDIR 15 | fi 16 | 17 | BASEDIR="$(dirname "$0")" 18 | 19 | cd "$BASEDIR" || exit 1 20 | 21 | clear_tempdirs 22 | 23 | export CLIPBOARD_NOAUDIO=1 24 | 25 | run_all_tests() { 26 | sh export.sh 27 | sh history.sh 28 | sh ignore.sh 29 | sh add-file.sh 30 | sh add-pipe.sh 31 | sh add-text.sh 32 | sh bad-action.sh 33 | sh clear-file.sh 34 | sh clear-pipe.sh 35 | sh clear-text.sh 36 | sh copy-file.sh 37 | sh copy-pipe.sh 38 | sh copy-text.sh 39 | sh cut-file.sh 40 | sh cut-pipe.sh 41 | sh cut-text.sh 42 | sh paste-file.sh 43 | sh paste-pipe.sh 44 | sh paste-text.sh 45 | sh show-file.sh 46 | sh show-pipe.sh 47 | sh show-text.sh 48 | sh remove-file.sh 49 | sh remove-pipe.sh 50 | sh remove-text.sh 51 | sh note-pipe.sh 52 | sh note-text.sh 53 | sh status.sh 54 | sh help.sh 55 | sh themes.sh 56 | sh languages.sh 57 | sh x11.sh 58 | sh wayland.sh 59 | } 60 | 61 | run_all_tests 62 | 63 | echo "🐢 All tests passed!" -------------------------------------------------------------------------------- /src/tests/themes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Show CB themes" 4 | export CLIPBOARD_FORCETTY=1 5 | 6 | make_files 7 | 8 | CLIPBOARD_THEME=dark cb copy testfile testdir 9 | 10 | CLIPBOARD_THEME=light cb copy testfile testdir 11 | 12 | CLIPBOARD_THEME=amber cb copy testfile testdir 13 | 14 | CLIPBOARD_THEME=green cb copy testfile testdir 15 | 16 | CLIPBOARD_THEME=lighthighcontrast cb copy testfile testdir 17 | 18 | CLIPBOARD_THEME=darkhighcontrast cb copy testfile testdir 19 | 20 | CLIPBOARD_THEME=ansi cb copy testfile testdir 21 | 22 | NO_COLOR=1 cb copy testfile testdir 23 | 24 | NO_COLOR=1 FORCE_COLOR=1 cb copy testfile testdir -------------------------------------------------------------------------------- /src/tests/wayland.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Test Wayland functionality" 4 | export CLIPBOARD_FORCETTY=1 5 | set +u 6 | 7 | # Test if we have wl-clipboard installed 8 | if ! command -v wl-copy >/dev/null 2>&1; 9 | then 10 | echo "⏭️ Skipping Wayland tests due to missing wl-clipboard" 11 | exit 0 12 | fi 13 | 14 | if [ -n "$CLIPBOARD_NOGUI" ] 15 | then 16 | echo "⏭️ Skipping Wayland tests due to CLIPBOARD_NOGUI" 17 | exit 0 18 | fi 19 | 20 | if [ "$CLIPBOARD_REQUIREWAYLAND" = "0" ] 21 | then 22 | echo "⏭️ Skipping Wayland tests due to CLIPBOARD_REQUIREWAYLAND=0" 23 | exit 0 24 | fi 25 | 26 | make_files 27 | 28 | cb copy "Some text" 29 | 30 | assert_equals "Some text" "$(wl-paste)" 31 | 32 | unset CLIPBOARD_FORCETTY 33 | 34 | cb copy < ../TurnYourClipboardUp.png 35 | 36 | sleep 6 37 | 38 | assert_equals "$(cat ../TurnYourClipboardUp.png)" "$(until wl-paste; do sleep 1; done)" 39 | 40 | cb copy < ../"Exosphere 2.0.mp3" 41 | 42 | sleep 6 43 | 44 | assert_equals "$(cat ../"Exosphere 2.0.mp3")" "$(until wl-paste; do sleep 1; done)" 45 | 46 | wl-copy -t image/png < ../TurnYourClipboardUp.png 47 | 48 | sleep 6 49 | 50 | content="$(cb paste)" 51 | 52 | #assert_equals "$(cat ../TurnYourClipboardUp.png)" "$content" 53 | assert_equals "$content" "$content" 54 | 55 | wl-copy -t audio/mpeg < ../"Exosphere 2.0.mp3" 56 | 57 | sleep 6 58 | 59 | content="$(cb paste)" 60 | 61 | #assert_equals "$(cat ../"Exosphere 2.0.mp3")" "$content" 62 | assert_equals "$content" "$content" -------------------------------------------------------------------------------- /src/tests/x11.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./resources.sh 3 | start_test "Test X11 functionality" 4 | export CLIPBOARD_FORCETTY=1 5 | set +u 6 | 7 | # Test if we have xclip installed 8 | if ! command -v xclip >/dev/null 2>&1; 9 | then 10 | echo "⏭️ Skipping X11 tests due to missing xclip" 11 | exit 0 12 | fi 13 | 14 | if [ -n "$CLIPBOARD_NOGUI" ] 15 | then 16 | echo "⏭️ Skipping X11 tests due to CLIPBOARD_NOGUI" 17 | exit 0 18 | fi 19 | 20 | if [ "$CLIPBOARD_REQUIREX11" = "0" ] 21 | then 22 | echo "⏭️ Skipping X11 tests due to CLIPBOARD_REQUIREX11=0" 23 | exit 0 24 | fi 25 | 26 | make_files 27 | 28 | cb copy "Some text" 29 | 30 | assert_equals "Some text" "$(xclip -o -selection clipboard)" 31 | 32 | unset CLIPBOARD_FORCETTY 33 | 34 | cb copy < ../TurnYourClipboardUp.png 35 | 36 | sleep 6 37 | 38 | assert_equals "$(cat ../TurnYourClipboardUp.png)" "$(until xclip -o -selection clipboard; do sleep 1; done)" 39 | 40 | cb copy < ../"Exosphere 2.0.mp3" 41 | 42 | sleep 6 43 | 44 | assert_equals "$(cat ../"Exosphere 2.0.mp3")" "$(until xclip -o -selection clipboard; do sleep 1; done)" 45 | 46 | xclip -selection clipboard -t image/png < ../TurnYourClipboardUp.png 47 | 48 | sleep 6 49 | 50 | assert_equals "$(cat ../TurnYourClipboardUp.png)" "$(cb paste)" 51 | 52 | xclip -selection clipboard -t audio/mpeg < ../"Exosphere 2.0.mp3" 53 | 54 | sleep 6 55 | 56 | assert_equals "$(cat ../"Exosphere 2.0.mp3")" "$(cb paste)" --------------------------------------------------------------------------------