User Tools

Site Tools


development:emacs:ediff

Ediff Mode

Because Ediff is a very useful Emacs mode (in particular for VC) i wrote a shell script to start it from the command line.

  1. #!/bin/bash
  2. #
  3. # Copyright (C) 2013-2020 Ralf Hoppe <ralf@dfcgen.de>
  4. #
  5. # ediff.sh
  6. #
  7. # Usage: ediff.sh [--client] LOCAL REMOTE [MERGED [BASE]]
  8. #
  9.  
  10. function abspath()
  11. {
  12. [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
  13. }
  14.  
  15.  
  16. MERGE=1 # if this is a MERGE
  17.  
  18. if [ $# -gt 0 ] && [ "$1" = "--client" ] ; then
  19. LOCAL=$(abspath "$2")
  20. REMOTE=$(abspath "$3")
  21. MERGED=$(abspath "$4")
  22. BASE=$(abspath "$5")
  23. EMACS_CMD="emacsclient --create-frame"
  24. # NOTE: Empty list `vc-handled-backends' is a workaround for Emacs 24
  25. # bug #18788, regarding vc-git mode-line.
  26. ELISP_COMMON=\
  27. "(setq rho/vc-handled-backends-backup vc-handled-backends \
  28. rho/ediff-frame (selected-frame) \
  29. cscope-initial-directory nil \
  30. vc-handled-backends ()) \
  31. (defun rho/ediff-quit-hook-external () \
  32. (setq vc-handled-backends rho/vc-handled-backends-backup) \
  33. (remove-hook 'ediff-quit-hook 'rho/ediff-quit-hook-external) \
  34. (delete-frame rho/ediff-frame)) \
  35. (add-hook 'ediff-quit-hook 'rho/ediff-quit-hook-external t)"
  36.  
  37. if [ -z "$(lsof -u $USER -a -c emacs 2>/dev/null | grep -w server)" ] ; then
  38. emacs --rho-minimal --no-site-file &
  39. sleep 3
  40. fi
  41.  
  42. sleep 1
  43. shift
  44. else
  45. LOCAL=$(abspath "$1")
  46. REMOTE=$(abspath "$2")
  47. MERGED=$(abspath "$3")
  48. BASE=$(abspath "$4")
  49. EMACS_CMD="emacs --rho-minimal --no-site-file"
  50. ELISP_COMMON=\
  51. "(setq ediff-quit-hook 'kill-emacs \
  52. vc-handled-backends ())"
  53. fi
  54.  
  55. if [ $# -lt 2 ]; then
  56. echo "Usage: $(basename $0) [--client] LOCAL REMOTE [MERGED [BASE]]"
  57. echo " (see also GIT-DIFFTOOL(1) and GIT-MERGETOOL(1))"
  58. exit 1
  59. fi
  60.  
  61. echo -e "$# files:\nLOCAL=$LOCAL\nREMOTE=$REMOTE"
  62.  
  63. if [ $# -eq 4 ] ; then
  64. echo -e "MERGED=$MERGED\nBASE=$BASE"
  65. $EMACS_CMD --eval \
  66. "(progn $ELISP_COMMON
  67. (setq-default ediff-show-clashes-only t)
  68. (ediff-merge-files-with-ancestor \"${LOCAL}\" \"${REMOTE}\" \"${BASE}\" nil \"${MERGED}\"))" > /dev/null
  69. elif [ $# -eq 2 -o "${REMOTE}" = "${MERGED}" ] ; then
  70. $EMACS_CMD --eval \
  71. "(progn $ELISP_COMMON
  72. (ediff-files \"$LOCAL\" \"$REMOTE\"))" > /dev/null
  73. MERGE=0
  74. else
  75. echo "MERGED=$MERGED"
  76. $EMACS_CMD --eval \
  77. "(progn $ELISP_COMMON
  78. (setq-default ediff-show-clashes-only t)
  79. (ediff-merge-files \"${LOCAL}\" \"${REMOTE}\" nil \"${MERGED}\"))" > /dev/null
  80. fi
  81.  
  82. if [ $MERGE -ne 0 ]; then
  83. EGREPHITS="$(egrep -c '^(<<<<<<<|>>>>>>>)' $MERGED)"
  84.  
  85. if [ $EGREPHITS -ne 0 ]; then
  86. TMPFILE="$(mktemp --tmpdir $(basename $MERGED).XXXXXXXXXX)"
  87. cp -p "$MERGED" "$TMPFILE"
  88. echo "Conflicts -> see file $TMPFILE"
  89. exit 1
  90. fi
  91. fi
  92.  
  93. exit 0
development/emacs/ediff.txt · Last modified: 2021/07/12 21:08 by Ralf H.