Giter VIP home page Giter VIP logo

ws-butler's Introduction

Build Status

ws-butler -- an unobtrusive way to trim spaces from end of line

  • Only lines touched get trimmed. If the white space at end of buffer is changed, then blank lines at the end of buffer are truncated respecting require-final-newline.

  • Trimming only happens when saving.

What does unobtrusive mean?

The user is not made explicitly aware when trimming happens. You keep working and the butler takes care of whitespace for you.

This means if point is at a location that was trimmed, point is not moved, but the data on disk has been cleaned up (revert the buffer to confirm).

Not moving point because of space deletion.

By default, ws-butler preserves "virtual spaces" in front of point if necessary. The file on disk is cleaned up however.

This can be disabled with ws-butler-keep-whitespace-before-point.

Trimming only specific lines.

There might be lines you don't want to get trimmed, e.g. spaces in multiline strings. The behavior can be customized through ws-butler-trim-predicate. This variable should hold a function that expects 2 arguments (region beginning and end) and should return true only for regions that one wants to get trimmed. As an example

(setq ws-butler-trim-predicate
      (lambda (beg end)
        (not (eq 'font-lock-string-face
                 (get-text-property end 'face)))))

Installation

Debian 9 or later or Ubuntu 16.10 or later

apt-get install elpa-ws-butler

Configuration

To use ws-butler, require it and add ws-butler-mode as a hook on any mode where you would like it to be enabled. For example, to enable for all programming language modes, add this to your .emacs:

(require 'ws-butler)
(add-hook 'prog-mode-hook #'ws-butler-mode)

Alternatively, you can use ws-butler-global-mode to turn it on everywhere.

History

  1. I started by trimming all spaces at EOL in source code in a "write-file-hook" when I started programming. It seemed like a great idea.

  2. Then I got a job working on a code base where no one else trimmed spaces, so my commits became super noisy. I wanted to stop being the "white space" police, so switched to ws-trim.

    • ws-trim works in a post-command-hook and trims white space while you edit.
    • This was too eager for me. For example, I would stop and scroll away to look at some code, and when I get back to continue, my indentation is gone.
    • It caused some problems with other customizations which also rely on post-command-hook.
  3. I started experimenting with using highlight-changes-mode to trim only lines I touch on save.

  4. Now, the dependency on highlight-changes-mode has been removed and we handle change changing through text properties ourselves.

ws-butler's People

Contributors

alevy03 avatar chris-martin avatar darwinawardwinner avatar ian-kelling avatar ilohmar avatar lewang avatar spwhitton avatar xificurc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ws-butler's Issues

ws-butler with desktop-save-mode and emacs --daemon

The combination of using emacs daemon, with desktop-saved buffers that had ws-butler minor mode enabled causes the emacs daemon to hang when trying to restore these buffers.

This is related to issues: #12 and #4
but none offered a solution for me.

I have manage to create a workaround by doing two things:

i) Configure desktop-save-mode to ignore ws-butler mode and the highlight-changes-mode that it is based on.

;;
;; enable desktop-save
(desktop-save-mode t)
;;
;; disable saving/reloading of ws-butler-mode and highlight-changes
(delete 'highlight-changes-mode desktop-minor-mode-handlers)
(add-to-list 'desktop-minor-mode-handlers '(highlight-changes-mode . nil) t)
(add-to-list 'desktop-minor-mode-handlers '(ws-butler-mode . nil) t)
(add-to-list 'desktop-minor-mode-table '(highlight-changes-mode nil) t)
(add-to-list 'desktop-minor-mode-table '(ws-butler-mode nil) t)

This is not enough. Enabling ws-butler-global-mode or using hooks of other modes to enable ws-butler in the standard way sill causes the emacs daemon to hang on startup.

ii). Enable ws-butler-mode in the after-make-frame-functions hook. If you want ws-butler-mode enabled globally then this is easy:

(defun jd/enable-ws-butler-global (frame)
  (ws-butler-global-mode))
(add-hook 'after-make-frame-functions 'jd/enable-ws-butler-global)

This will enable ws-butler eveywhere every time a new frame is created.

However, if you want ws-butler to be enabled for certain modes via mode-hooks, say just for c-mode, then it's tricky. The related files, e.g. of c-mode, are already loaded on daemon startup by dekstop-save-mode and their hooks have already executed. To get around this, we need to register the hooks and revert all buffers (that have a file) only on the first created frame.

;;
;; ws-buttler setup
(defun jd/setup-ws-butler-hooks ()
  "Register hooks to enable ws-buttler"
  (require 'ws-butler)
  (add-hook 'prog-mode-hook 'ws-butler-mode)
  (add-hook 'c-mode-common-hook 'ws-butler-mode)
  (add-hook 'text-mode 'ws-butler-mode)
  (add-hook 'fundamental-mode 'ws-butler-mode))
;;
;; workaround on ws-butler inhibit emacs daemon startup
(setq jd/frame-rendered-flag nil)
;;
;; revert buffers in frame so that hooks re-run
(defun jd/revert-buffers-in-frame-and-reload-modes (frame)
  "Refreshes all open buffers from their respective files in the given frame, reloading any modes."
  (dolist (buf (buffer-list frame))
    (with-current-buffer buf
      (when (and (buffer-file-name) (file-exists-p (buffer-file-name)) (not (buffer-modified-p)))
        (revert-buffer t t nil)
        (message "Reloading file %s" (buffer-file-name))))))
;;
;; if flag not set, register hooks for ws-butler, revert buffers
(defun jd/enable-ws-butler (frame)
  (unless jd/frame-rendered-flag
    (jd/setup-ws-butler-hooks)
    (jd/revert-buffers-in-frame-and-reload-modes frame)
    (setq jd/frame-rendered-flag t))) 

(add-hook 'after-make-frame-functions 'jd/enable-ws-butler)

It seems to me that, the problem of using ws-butler with emacs --daemon and desktop-save-mode is due to ws-buttler or one of its dependencies really really wanting X11 to be present, which at the startup of emacs --daemon is not. This means we have to go through all this pain to make it work.

Can the developers investigate if the issue is due to ws-butler and fix it, or point to suspected dependecy packages, e.g. highlight-changes-mode?

white space before point trimmed in non focused buffer

When a buffer with ws-butler-mode enabled is saved, but is not in focus (not current buffer), ws-butler-keep-whitespace-before-point is not honored, and "virtual spaces" in front of point are not preserved.

To reproduce, start with emacs -Q, then setup:

(add-to-list 'load-path "~/.emacs.d/elpa/ws-butler-0.6/")
(require 'ws-butler)
(ws-butler-global-mode)

Visit a file visiting buffer, say "test1.txt", and type "word " (that is, "word" and a space) and leave point there. Visit a second file, say "test2.txt", and from there run save-some-buffers ("C-x s"). Emacs asks for confirmation to save "text1.txt", say "y". Switch back to "text1.txt" and see that the space after "word" and before point is gone.

A slight variation where you can actually see this happening is to do the same, but from a different window. Thus. Visit "test1.txt", split the window in two with "C-x 2", switch to "text2.txt", run save-some-buffers ("C-x s"), confirm.

Example tested on GNU Emacs 28.2 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2022-09-12 with ws-butler-0.6.

MELPA?

Can you add this to MELPA? :)

Please tag a new release

It would be great if you could make a new release. The rewrite to avoid highlight-changes-mode is more recent than the latest tagged release. Thanks.

Please don't look at indent-tabs-mode

First of all, thanks for this definitely needed package!

Now, I'll try to explain my request:

  • Personally, I do write code without tabs at all. I do have:

    ;; Indentation can't insert TABs.
    (setq-default indent-tabs-mode nil)

    in my Emacs configuration file.

  • When editing someone else's code, they often use TABs to indent. In order to respect the spirit of the file, I do insert TABs explicitly (with C-q TAB)... but those get removed by ws-butler at save time...

Could you either never look at indent-tabs-mode, or add a variable to customize that?

Thanks a lot!

Don't propertize minibuffer input

When I enable ws-butler, minibuffer gets propertized.

For instance, the helm-pattern variable in all Helm candidate functions looks like

#("foo" 0 2 (ws-butler-chg chg))

instead of

"foo"

This breaks numerous Helm packages, including Helm SLY (joaotavora/sly#370), but not only that, other modes suffer from this issue:

hrs/engine-mode#43

Any way to fix this?

org-element-cache warning when saving with ws-butler-keep-whitespace-before-point

affected version:

GNU Emacs     v27.2           
Doom core     v3.0.0-dev      
Doom modules  v22.08.0-dev     grafted, HEAD -> master, origin/master, origin/HEAD c44bc81 2022-08-19 11:24:34 +0200
Org mode version 9.6 (9.6-??-00adad9)

problem

  • ws-butler-keep-whitespace-before-point set to t
  • org-element-use-cache is set to t
  • saving an orgmode buffer, with trailing spaces before the point
  • warning pops up:
Warning (org-element-cache): org-element--cache: Unregistered buffer modifications detected. Resetting.
If this warning appears regularly, please report the warning text to Org mode mailing list (M-x org-submit-bug-report).
The buffer is: xyz.org
 Current command: nil
 Backtrace:
"  backtrace-to-string(nil)
  org-element--cache-sync(#<buffer xyz.org>)
  apply(org-element--cache-sync #<buffer xyz.org>)
  timer-event-handler([t 0 5 323697 nil org-element--cache-sync (#<buffer xyz.org>) idle 850999])
"

notes

  • i think it is because ws-butler-after-save modifies the buffer while inhibiting org-element change-hook functions to run (org-element--cache-before-change and/or org-element--cache-after-change)
  • see fix in org-transclusion for a solution to a similar problem
  • workaround is disabling org-element cache ๐Ÿ˜’

Feature request: trim at line change

I highlight trailing whitespace in bright red.

Steps:

  • add a new line to source code, so that the new line is automatically indented (e.g. after a curly in a C-like language),
  • navigate away from the line, C-n.

Result:

  • the indentation whitespace on the newly created line is highlighted, until I save the file.

Solution:

  • do the trimming at leaving the line, or give an option to do so.

This is what keeps me using ws-trim instead of ws-butler. Would you consider implementing something like this?

ws-butler adds a whole string of spaces at the end of file.

When I save a file ws-butler adds a string of spaces at the end of the file.
In the screenshot one can see 65 spaces were added. (Note that whitespace-mode disrupts the table layout.) Is there a way to prevent this from happening? I see it is not saved as it is added after, but still is a bit inconvenient on continued editing.

Screenshot-2023-05-07-11:36:11

ws-butler inhibits emacs daemon

My emacs daemon was failing, so I started disassembling my .emacs.d. If I strip my .emacs to this

(require 'package)
(ws-butler-global-mode +1)

Launching emacs --daemon fails to start (hangs), with this error:

Error in post-command-hook (ws-butler-global-mode-check-buffers): (error "X windows are not in use or not initialized")

This is the minimal setup that reproduces this.

Include ws-butler in Emacs

Somebody submitted a similar feature to emacs-devel and I mentioned your package. The Emacs maintainer said that he would be happy to incorporate a feature like this.

This is the thread in emacs-devel:

http://thread.gmane.org/gmane.emacs.devel/180282

The code on the initial message is based on post-commit-hook, something that you tried and discarded. It is not wrapped in a minor mode either, so it is hardly acceptable for Emacs in that state.

Please consider submitting ws-butler to Emacs.

Undo data corrupted

Modifying buffer text using with-silent-modifications can corrupt undo data. Let's preserve the modification flag this way instead.

diff --git a/ws-butler/ws-butler.el b/ws-butler/ws-butler.el
index 997a48e7fd..2afed1aeac 100644
--- a/ws-butler/ws-butler.el
+++ b/ws-butler/ws-butler.el
@@ -263,7 +263,7 @@ ensure point doesn't jump due to white space trimming."
   (ws-butler-clear-properties)
   ;; go to saved line+col
   (when ws-butler-presave-coord
-    (with-silent-modifications
+    (progn
       (let (remaining-lines)
         (ws-butler-with-save
          (widen)
@@ -273,7 +273,8 @@ ensure point doesn't jump due to white space trimming."
           (insert (make-string remaining-lines ?\n))))
       (move-to-column (cadr ws-butler-presave-coord))
       (when (< (current-column) (cadr ws-butler-presave-coord))
-        (insert (caddr ws-butler-presave-coord))))))
+        (insert (caddr ws-butler-presave-coord)))
+      (set-buffer-modified-p nil))))
 
 (defun ws-butler-before-revert ()
   "Clear `ws-butler-presave-coord'."

Sharp-quote all functions

All functions should be sharp-quoted instead of being quoted (important when byte-compiling).
In byte compilation, it causes its argument to be compiled:

        (add-hook 'after-change-functions 'ws-butler-after-change t t)

should be

        (add-hook 'after-change-functions #'ws-butler-after-change t t)

Define a globalized minor mode

...so that the user doesn't need to enable this per-hook.

Also, ;;;###autoload blocks for both the minor mode and the globalized mode wouldn't hurt.

Use cl-lib, not cl

ws-butler uses (eval-when-compile (require 'cl)). That's fine as far as namespace pollution goes, but it generates a byte compilation warning, since cl is deprecated. Please switch to using cl-lib.

Assorted gripes

  1. unobstrusively has an extraneous s inside.
  2. (require 'ws-butler) signals error "Required feature was not provided".
  3. If the line has trailing whitespace and the point is at the end of it when the buffer is saved, that whitespace is not cleared.
  4. No replacing of tabs with spaces or removing trailing newlines.

Overall, I like how small the package is. Good idea reusing highlight-changes-mode.

ws-butler fails with fci-mode enabled

If fci-mode (from the fill-column-indicator package in melpa-stable) is enabled then trailing whitespace is no longer shown in a different face. This happens even where all of the trailing whitespace is to the right of the rule.

How do I get EOB blank lines to be cleaned?

I have tried to get ws-butler to remove EOB blank lines, but they always remain, no matter where I touch the file near these lines. My lisp is not the best, so I am not sure how to debug this or determine how to trigger cleaning of these lines.

Incompatible with Magit

Hi,

I've noticed an unfortunate behavior. If I make changes to a file, and then discard a particular hunk using Magit, ws-butler is counting that as a change to the entire file, and proceeds to do a whitespace cleanup of the entire file.

I can do more investigating later, but thought I should bring this to your attention.

FWIW I have Magit set to auto-revert the buffer.

Compilation warnings with ws-butler 0.6

The following appears in the *Warnings* buffer when Emacs 28 starts for the first time with native compilation enabled:

Warning (comp): ws-butler.el:59:13: Warning: Package cl is deprecated Disable showing Disable logging
Warning (comp): ws-butler.el:153:8: Warning: docstring wider than 80 characters Disable showing Disable logging

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.