Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I donate these scripts to you? #54

Closed
koraa opened this issue Jul 22, 2023 · 5 comments
Closed

Can I donate these scripts to you? #54

koraa opened this issue Jul 22, 2023 · 5 comments

Comments

@koraa
Copy link

koraa commented Jul 22, 2023

The following scripts support:

  • Bidirectional clipboard syncing between primary and clipboard
  • Properly preserve newlines
  • Moving the clipboard into cliphist
  • Systemd user units
  • They do not hang my sway window manager as copyq does… (although sway should really be fixing this)

They do not support informing cliphist about the mime type; they are also a bit inefficient as many commands are started to make this setup work. A pure go/rust solution might be better suited for efficiency.

~/.config/systemd/user/cliphist.helper.sh

#! /bin/bash

# This script is designed to preserve the exact contents of th
# A note about newline preserving string handling in bash
#
# $ mycommand <<< "${foo}" – # appends a newline
# $ echo -n "${foo}" | mycommand # preserves newline
# $ foo="$(cat)" # preserves newline
# $ foo="$(</dev/stdin)" # preserves newline
# $ $'\n' # String literal with explicit newline handling
# $ LF=$'\n' # Line feed (newline) as a variable
# $ "${LF}" # Regular string literal with newlines
# $ wl-copy -n # trims newlines - DOES NOT PRESERVE NEWLINES
# $ wl-copy # preserves newlines
# $ wl-paste -n # preserves newlines
# $ wl-paste # adds a newline - DOES NOT PRESERVE NEWLINES

set -e
SCRIPT_SOURCE="$0"
DEBUG="falsfalse"
LF=$'\n'

log() {
  echo >&2 "$@"
}

dbg() {
  if check "${DEBUG}"; then
    log "$@"
  fi
}

show_newlines() {
  printf "%q" "$1"
}

exc() {
  if check "${DEBUG}"; then
    local stdin; stdin="$(cat)"
    log -e "$ $*\n< $(show_newlines "${stdin}")"
    echo -n "${stdin}" | "$@"
  else
    "$@"
  fi
}

panic() {
  log "Panic:" "$@"
  exit 1
}

bool() {
  if "$@"; then
    echo true
  else
    echo false
  fi
}

check() {
  test "$1" = "true"
}

cmd_sync_write() {

  local src_args; src_args=()
  local dst_args; dst_args=()

  local remember; remember="false"
  local primary; primary="false"

  while (( "$#" > 0 )); do
    case "$1" in
      "--primary") # Write to primary selection
        primary="true"
        ;;
      "--remember") # Notify cliphist
        remember="true"
        ;;
      *)
        panic "Unknown sync parameter: $1"
    esac
    shift
  done

  if check "${primary}"; then
    dst_args+=("--primary")
  else
    src_args+=("--primary")
  fi

  local nu; nu="$(</dev/stdin)"
  local nu_mime; nu_mime="$(wl-paste --list "${src_args[@]}" | head -n1)"
  local cur; cur="$(wl-paste -n "${dst_args[@]}")"
  local cur_mime; cur_mime="$(wl-paste --list "${dst_args[@]}" | head -n1)"
  local novel; novel="$(bool test "${nu}" != "${cur}" -o "${nu_mime}" != "${cur_mime}")"

  if check "${DEBUG}"; then
    dbg "sync_write!" \
      "remember=${remember}" \
      "novel=${novel}" \
      "primary=${primary}" \
      "nu=${nu_mime}:$(show_newlines "${nu}")" \
      "cur=${cur_mime}:$(show_newlines "${cur}")" \
      -- src_args = "${src_args[@]}" \
      -- dst_args = "${dst_args[@]}" \
      -- '$@' = "$@"
  fi

  # Send clipboard data to cliphist
  if check "${remember}"; then
    # TODO: Support mime
    echo -n "${nu}" | exc cliphist store
  fi

  # Avoid infinite update loops by detecting if the destination clipboard contains the data already
  if check "${novel}"; then
    echo -n "${nu}" | exc exec wl-copy --type "${nu_mime}" "${dst_args[@]}"
  fi

}

cmd_watch() {
  if (( "$#" > 1 )); then
    panic -e "Spurious arguments: ${*}${LF}Just specify a single argument --primary or --clipboard"
  fi

  local mode; mode="$1"; shift || panic "Please specify --primary or --clipboard"
  local primary; primary="false"
  case "${mode}" in
    "--primary")
      # From primary, to cliboard; to cliphist via the clipboard handler
      primary="false"
      ;;
    "--clipboard")
      # From clipboard, to primary and cliphist
      primary="true"
      ;;
    *)
      panic "Unknown mode: ${mode}. Please specify --primary or --clipboard"
  esac

  local watch_opts; watch_opts=()
  local sync_opts; sync_opts=()

  if [[ "$primary" = "true" ]]; then
    # primary -> clipboard -> cliphist
    watch_opts=("--primary" "${watch_opts[@]}")
  else
    # clipboard -> primary, cliphist
    sync_opts=("--remember" "${sync_opts[@]}")
    sync_opts=("--primary" "${sync_opts[@]}")
  fi

  exc exec wl-paste -n "${watch_opts[@]}" -w bash "${SCRIPT_SOURCE}" sync_write "${sync_opts[@]}"
}

main() {
  local cmd; cmd="$1"; shift || panic "Specify a command"
  if [[ "$cmd" = "sync_write" ]]; then
    cmd_sync_write "$@"
  elif [[ "$cmd" = "watch" ]]; then
    cmd_watch "$@"
  else
    panic "Unknown command ${cmd}"
  fi
}

main "$@"

~/.config/systemd/user/cliphist.service

[Unit]
Description=Cliphist clipboard manager
After=sway.target
Wants=sway.target
Requires=cliphist-watch-primary.service
Requires=cliphist-watch-clipboard.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true

[Install]
WantedBy=default.target

~/.config/systemd/user/cliphist-watch-primary.service

[Unit]
Description=Cliphist clipboard manager
PartOf=cliphist.service
ReloadPropagatedFrom=cliphist.service

[Service]
Type=simple
ExecStart=/usr/bin/bash "%Y/cliphist.helper.sh" watch --primary
Restart=always
RestartSec=1
TimeoutStopSec=10
KillMode=mixed

~/.config/systemd/user/cliphist-watch-clipboard.service

[Unit]
Description=Cliphist clipboard manager
PartOf=cliphist.service
ReloadPropagatedFrom=cliphist.service

[Service]
Type=simple
ExecStart=/usr/bin/bash "%Y/cliphist.helper.sh" watch --clipboard
Restart=always
RestartSec=1
TimeoutStopSec=10
KillMode=mixed
@sentriz
Copy link
Owner

sentriz commented Jul 22, 2023

hi I'm not sure why special handing of newlines is required, that's what cliphist decode is for

@koraa
Copy link
Author

koraa commented Jul 22, 2023

hi I'm not sure why special handing of newlines is required, that's what cliphist decode is for

There is no special handling. Bash and wl-copy are simply erasing the information about whether there is a trailing newline by default…

@sentriz
Copy link
Owner

sentriz commented Jul 24, 2023

ah ok i think i see it now 👍

there is already a contrib/ dir here but i was thinking of moving that stuff to a wiki instead of checking them in - since i don't use these scripts personally and don't want to have to maintain them as cliphist evolves

i just changed the github settings and i think you can edit the wiki now. does that work?

thanks!

@koraa
Copy link
Author

koraa commented Jul 24, 2023

Since neither you nor I wish to maintain them they will have to go to the abyss of forgotten software.
It is a shame really, cliphist is of very limited use without them %)

@koraa koraa closed this as completed Jul 24, 2023
@koraa
Copy link
Author

koraa commented Jul 24, 2023

In case anyone else wishes to pick these scripts up, I hereby license them under a CC0 (Public Domain) license.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants