Skip to content

Commit

Permalink
treewide: Rewrite in C
Browse files Browse the repository at this point in the history
Over the past couple of years I've thought about rewriting clipmenu
(both client and daemon) in C. Among many other reasons supporting this
are:

- clipmenu and friends as they stand right now in bash are fairly
  unwieldy. They have over time built up a lot of workarounds and hacks
  for xclip/xsel behaviour, and cases where bash itself works against us
  (like the way it handles newlines in command substitution). All in
  all, it makes more sense to have more granular control with Xlib
  itself.
- xclip/xsel have nasty edge cases. Just as one example, the fact that
  we take ownership when there's not even an XA_STRING/UTF8_STRING
  target with the current logic is one of the main things which have
  resulted in bug reports like issue #188 which are hard to work around,
  and make clipmenu not usable for some workflows.
- In general, using Xlib allows us to be more careful about how we
  implement things like owning the clipboard, instead of hacks like how
  we currently implement `CM_SYNC_PRIMARY_TO_CLIPBOARD` and its ilk.

The new version also introduces support for a config file at
~/.config/clipmenu/clipmenu.conf, as opposed to always having to use
environment variables. Documentation right now is sparse (read:
nonexistent), but you can look at config_setup_internal. Before release
it will be documented properly.

This new C version will become clipmenu 7.

Breaking changes to invocation:

- CM_LAUNCHER=rofi-script mode is removed (if more than one person used
  this maybe I will reconsider, but it doesn't work well with the new
  indexing logic in clipmenu so we need to think about how that should
  work).
- CM_LAUNCHER=fzf now requires CM_LAUNCHER_PASS_DMENU_ARGS=0. You can,
  in general, use any launcher like this now and just pass whatever args
  you want via clipmenu itself.
- clipfsck is gone, not that it ever really did much anyway.
  • Loading branch information
cdown committed Apr 9, 2024
1 parent 9735907 commit ef0afe0
Show file tree
Hide file tree
Showing 25 changed files with 2,752 additions and 715 deletions.
10 changes: 10 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
BinPackArguments: true
BreakStringLiterals: false
ColumnLimit: 80
IndentCaseLabels: true
IndentPPDirectives: BeforeHash
IndentWidth: 4
PenaltyBreakComment: 0
SortIncludes: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
UseTab: Never
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
jobs:
build_and_test:
name: CI
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- run: sudo apt-get update

- uses: awalsh128/cache-apt-pkgs-action@v1
with:
packages: gcc-10 clang clang-format clang-tidy cppcheck xvfb xsel libxfixes-dev libx11-dev
version: 1.0

- run: gcc --version

- run: make clean analyse
- run: tests/x_integration_tests

on:
push:
pull_request:
workflow_dispatch:
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
src/clipmenud
src/clipctl
src/clipdel
src/clipmenu
src/clipserve
tests/test
*.o
24 changes: 20 additions & 4 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
This is free and unencumbered software released into the public domain.
The MIT License

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
Copyright (c) 2014-present Christopher Down

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
101 changes: 89 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,89 @@
# `dmenu` is not a hard dependency, but you need it unless
# you plan to set CM_LAUNCHER to another value like `rofi`
REQUIRED_BINS := xsel clipnotify
PREFIX ?= /usr
$(foreach bin,$(REQUIRED_BINS),\
$(if $(shell command -v $(bin) 2> /dev/null),$(info Found `$(bin)`),$(error Missing Dep. Please install `$(bin)`)))

.PHONY: install

install:
install --target "${PREFIX}/bin" -D -m755 clipmenu clipmenud clipdel clipctl
install -D -m644 init/clipmenud.service "${PREFIX}/lib/systemd/user/clipmenud.service"
CFLAGS := -std=gnu11 -O2 -Wall -Wextra -Wshadow -Wpointer-arith \
-Wcast-align -Wmissing-prototypes -Wstrict-overflow -Wformat=2 \
-Wwrite-strings -Warray-bounds -Wstrict-prototypes \
-Werror $(CFLAGS)
CPPFLAGS := -I/usr/X11R6/include -L/usr/X11R6/lib
LDLIBS := -lX11 -lXfixes
PREFIX ?= /usr/local
bindir := $(PREFIX)/bin
debug_cflags := -D_FORTIFY_SOURCE=2 -fsanitize=leak -fsanitize=address \
-fsanitize=undefined -Og -ggdb -fno-omit-frame-pointer \
-fstack-protector-strong
c_files := $(wildcard src/*.c)
h_files := $(wildcard src/*.h)
libs := $(filter $(c_files:.c=.o), $(h_files:.h=.o))

bins := clipctl clipmenud clipdel clipserve clipmenu

all: $(addprefix src/,$(bins))

src/%: src/%.c $(libs)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) $^ -o $@

src/%.o: src/%.c src/%.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

debug: all
debug: CFLAGS+=$(debug_cflags)

install: all
mkdir -p $(DESTDIR)$(bindir)/
install -pt $(DESTDIR)$(bindir)/ $(addprefix src/,$(bins))
install -Dp -m 644 init/clipmenud.service $(DESTDIR)$(PREFIX)/lib/systemd/user/clipmenud.service

uninstall:
rm -f $(addprefix $(DESTDIR)$(PREFIX)/bin/,$(bins))
rm -f "$(DESTDIR)${PREFIX}/lib/systemd/user/clipmenud.service"

clean:
rm -f src/*.o src/*~ $(addprefix src/,$(bins))

clang_supports_unsafe_buffer_usage := $(shell clang -x c -c /dev/null -o /dev/null -Werror -Wunsafe-buffer-usage > /dev/null 2>&1; echo $$?)
ifeq ($(clang_supports_unsafe_buffer_usage),0)
extra_clang_flags := -Wno-unsafe-buffer-usage
else
extra_clang_flags :=
endif

c_analyse_targets := $(c_files:%=%-analyse)
h_analyse_targets := $(h_files:%=%-analyse)

analyse: CFLAGS+=$(debug_cflags)
analyse: $(c_analyse_targets) $(h_analyse_targets)

$(c_analyse_targets): %-analyse:
# -W options here are not clang compatible, so out of generic CFLAGS
gcc $< -o /dev/null -c \
-std=gnu99 -Ofast -fwhole-program -Wall -Wextra \
-Wlogical-op -Wduplicated-cond \
-fanalyzer $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
clang $< -o /dev/null -c -std=gnu99 -Ofast -Weverything \
-Wno-documentation-unknown-command \
-Wno-language-extension-token \
-Wno-disabled-macro-expansion \
-Wno-padded \
-Wno-covered-switch-default \
-Wno-gnu-zero-variadic-macro-arguments \
-Wno-declaration-after-statement \
-Wno-cast-qual \
-Wno-unused-command-line-argument \
$(extra_clang_flags) \
$(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
$(MAKE) $*-shared-analyse

$(h_analyse_targets): %-analyse:
$(MAKE) $*-shared-analyse

%-shared-analyse: %
# cppcheck is a bit dim about unused functions/variables, leave that to
# clang/GCC
cppcheck $< --std=c99 --quiet --inline-suppr --force \
--enable=all --suppress=missingIncludeSystem \
--suppress=unusedFunction --suppress=unmatchedSuppression \
--suppress=unreadVariable \
--max-ctu-depth=32 --error-exitcode=1
# clang-analyzer-unix.Malloc does not understand _drop_()
clang-tidy $< --quiet -checks=-clang-analyzer-unix.Malloc -- -std=gnu99
clang-format --dry-run --Werror $<

.PHONY: all debug install uninstall clean analyse
52 changes: 0 additions & 52 deletions clipctl

This file was deleted.

95 changes: 0 additions & 95 deletions clipdel

This file was deleted.

28 changes: 0 additions & 28 deletions clipfsck

This file was deleted.

Loading

0 comments on commit ef0afe0

Please sign in to comment.