Keyboard scrolling with acceleration - emacs

One can easily map some key to scroll up.
(defun up1()
(interactive)
(scroll-up 1))
(defun up2()
(interactive)
(scroll-up 2))
(global-set-key "\M-]" 'up2)
I am looking instead for the following behavior. The first handful of
scrolls would call up1() and the subsequent ones would call up2().

How about this:
(setq my-scroll-counter 0)
(setq my-scroll-limit 5)
(defun up1()
(interactive)
(if (eq last-command this-command)
(incf my-scroll-counter)
(setq my-scroll-counter 0))
(if (> my-scroll-counter my-scroll-limit)
(scroll-up 2)
(scroll-up 1)))
(global-set-key "\M-]" 'up1)
If you want something a little fancier, you calculate your scroll step dynamically based on how many times you repeat the command:
(setq my-scroll-counter 0)
(setq my-maximum-scroll 20)
(setq my-scroll-acceleration 4)
(defun up1()
(interactive)
(if (eq last-command this-command)
(incf my-scroll-counter)
(setq my-scroll-counter 0))
(scroll-up (min
(+ 1 (/ my-scroll-counter my-scroll-acceleration))
my-maximum-scroll)))
(global-set-key "\M-]" 'up1)

Related

Moving lines internally in emacs 24.4

I have this snippet of code in my .emacs file that should move lines of code up or down. This works fine on 24.3.1 but not fully on 24.4.
moving lines down work, as the line would be swapped with the bottom line and the "cursor" would move as well.
Moving the line up however, it will swap but the cursor stay on the same line without moving up along with the line.
Is there a reason for that?
;; Moving a line up or down
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
;(global-set-key [M-S-down] 'move-text-down)
(global-set-key [A-M-down] 'move-text-down)
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
;(global-set-key [M-S-up] 'move-text-up)
(global-set-key [A-M-up] 'move-text-up)

Make frames in Emacs GUI behaves like frames in Terminal

In terminal, Emacs manage multiple frames with names like F1, F2.... because it can't create multiple OS windows. I want the GUI version to behave this way, that is, instead of creating multiple OS windows, I want it to create many virtual frames inside a single Emacs window. Is there a way?
There is a way to mimic the frame switching behavior of terminal emacs in GUI. Here is what I did. Basicly it uses make-frame-invisible to hide inactive frames. It works well on archlinux with i3.
(defsubst +amos--is-frame-daemons-frame (f)
(and (daemonp) (eq f terminal-frame)))
(defun +amos--frame-list-without-daemon ()
"Return a list of frames without the daemon's frame."
(if (daemonp)
(filtered-frame-list
#'(lambda (f) (not (+amos--is-frame-daemons-frame f))))
(frame-list)))
(defun +amos/workspace-new ()
(interactive)
(let ((name (frame-parameter nil 'name))
(oframe (selected-frame)))
(select-frame (if (s-starts-with? "F" name)
(make-frame)
(make-frame `((name . ,name)))))
(make-frame-invisible oframe t))
(setq +amos--frame-list (reverse (+amos--frame-list-without-daemon))))
(setq +amos-tmux-need-switch nil)
;; TODO ring lru
(defun +amos/workspace-delete ()
(interactive)
(let ((f (selected-frame)))
(select-frame (previous-frame))
(make-frame-visible)
(delete-frame f))
(setq +amos--frame-list (reverse (+amos--frame-list-without-daemon)))
(+doom-modeline|set-selected-window)
(realign-windows)
(when +amos-tmux-need-switch
(shell-command! "tmux switch-client -t amos\; run-shell -t amos '/home/amos/scripts/setcursor.sh $(tmux display -p \"#{pane_tty}\")'")
(setq +amos-tmux-need-switch nil)))
(defun +amos/workspace-switch-to (index)
(interactive)
(when (< index (length +amos--frame-list))
(let ((frame (nth index +amos--frame-list))
(oframe (selected-frame)))
(select-frame frame)
(raise-frame frame)
(make-frame-invisible oframe t)
(setq +amos-tmux-need-switch nil)
(realign-windows)
(recenter))))
(defun +amos/workspace-switch-to-1 () (interactive) (+amos/workspace-switch-to 0))
(defun +amos/workspace-switch-to-2 () (interactive) (+amos/workspace-switch-to 1))
(defun +amos/workspace-switch-to-3 () (interactive) (+amos/workspace-switch-to 2))
(defun +amos/workspace-switch-to-4 () (interactive) (+amos/workspace-switch-to 3))
(defun +amos/workspace-switch-to-5 () (interactive) (+amos/workspace-switch-to 4))
(defun +amos/workspace-switch-to-6 () (interactive) (+amos/workspace-switch-to 5))
(defun +amos/workspace-switch-to-7 () (interactive) (+amos/workspace-switch-to 6))
(defun +amos/workspace-switch-to-8 () (interactive) (+amos/workspace-switch-to 7))
(defun +amos/workspace-switch-to-9 () (interactive) (+amos/workspace-switch-to 8))
(defun +amos-workspace-cycle (off)
(let* ((n (length +amos--frame-list))
(index (-elem-index (selected-frame) +amos--frame-list))
(i (% (+ off index n) n)))
(+amos/workspace-switch-to i)))
(defun +amos/workspace-switch-left () (interactive) (+amos-workspace-cycle -1))
(defun +amos/workspace-switch-right () (interactive) (+amos-workspace-cycle +1))
(defun +amos|maybe-delete-frame-buffer (frame)
(let ((windows (window-list frame)))
(dolist (window windows)
(let ((buffer (window-buffer (car windows))))
(when (eq 1 (length (get-buffer-window-list buffer nil t)))
(kill-buffer buffer))))))
(add-to-list 'delete-frame-functions #'+amos|maybe-delete-frame-buffer)
If what you mean is that you want to be able to access frames by name, then yes, you can do this with Icicles.
By default, C-x 5 o is bound to multi-command icicle-select-frame. This lets you select one or more frames by name.
A frame's name comes from its name frame parameter. It is suffixed as needed by [NUMBER], to
make it unique. For example, in a context where frames are named for
their buffers and you have two frames showing buffer *Help*, one of
the frames will be called *Help*[2] for use with this command.
Frame selection with C-x 5 o uses completion and cycling. The completion can be vanilla Emacs completion or regexp (including, of course, substring) completion. (It can also be any of several fuzzy completions.)
(If, for some reason, you want the frame names to be just F1, F2, etc., as with terminal Emacs, then you just need to do that at the level of frame parameter name. You can do that using hooks etc.)

Toggle case of next letter in elisp

I'd like to be able to toggle the case of the letter under the point. To that end, I wrote this:
(defun toggle-case-next-letter ()
"Toggles the case of the next letter, then moves the point forward one character"
(interactive)
(let* ((p (point))
(upcased (upcasep (char-after)))
(f (if upcased 'downcase-region 'upcase-region)))
(progn
(f p (+ 1 p))
(forward-char))))
However, when I run it (I've bound it to M-#), I get progn: Symbol's function definition is void: f. I assume this means f isn't bound, but I'm not sure.
Upcasep is defined as:
(defun upcasep (c) (eq c (upcase c)))
Is the problem in the let binding, or something else? (Also, if there's a better way to do this, that'd be nice as well).
Note that originally I had (upcased (upcasep (buffer-substring-no-properties p (+ 1 p)))), which I've corrected to (upcased (upcasep (char-after)), because using upcasep as defined above is always nil for strings (so I couldn't downcase again).
You've got a typical case of lisp-1 / lisp-2 confusion. Here's a fix (just a funcall):
(defun toggle-case-next-letter ()
"Toggles the case of the next letter, then moves the point forward one character"
(interactive)
(let* ((p (point))
(upcased (char-upcasep (buffer-substring-no-properties p (+ 1 p))))
(f (if upcased 'downcase-region 'upcase-region)))
(progn
(funcall f p (+ 1 p))
(forward-char))))
And here's what I have:
(global-set-key (kbd "C->") 'upcase-word-toggle)
(global-set-key (kbd "C-z") 'capitalize-word-toggle)
(defun char-upcasep (letter)
(eq letter (upcase letter)))
(defun capitalize-word-toggle ()
(interactive)
(let ((start (car
(save-excursion
(backward-word)
(bounds-of-thing-at-point 'symbol)))))
(if start
(save-excursion
(goto-char start)
(funcall
(if (char-upcasep (char-after))
'downcase-region
'upcase-region)
start (1+ start)))
(capitalize-word -1))))
(defun upcase-word-toggle ()
(interactive)
(let ((bounds (bounds-of-thing-at-point 'symbol))
beg end
regionp)
(if (eq this-command last-command)
(setq regionp (get this-command 'regionp))
(put this-command 'regionp nil))
(cond
((or (region-active-p) regionp)
(setq beg (region-beginning)
end (region-end))
(put this-command 'regionp t))
(bounds
(setq beg (car bounds)
end (cdr bounds)))
(t
(setq beg (point)
end (1+ beg))))
(save-excursion
(goto-char (1- beg))
(and (re-search-forward "[A-Za-z]" end t)
(funcall (if (char-upcasep (char-before))
'downcase-region
'upcase-region)
beg end)))))
I couldn't get #abo-abo's answer working for me but using his comments I was able to google better and found the following at http://chneukirchen.org/dotfiles/.emacs
(defun chris2-toggle-case ()
(interactive)
(let ((char (following-char)))
(if (eq char (upcase char))
(insert-char (downcase char) 1 t)
(insert-char (upcase char) 1 t)))
(delete-char 1 nil)
(backward-char))
(global-set-key (kbd "M-#") 'chris2-toggle-case)
This answers the original question if you remove (backward-char).
I realize this is a very old question, but having stumbled upon the same problem recently, I'd like to suggest a simpler solution.
I start with a pure function for toggling character case, based on char code property inspection:
(cl-defun toggle-char-case (c)
(cl-case (get-char-code-property c 'general-category)
(Lu (downcase c))
(Ll (upcase c))
(t c)))
I then use it from within an interactive function operating at point:
(cl-defun toggle-char-case-at-point ()
(interactive)
(let ((new (toggle-char-case (char-after))))
(delete-char 1)
(insert new)))
I then bound this interactive function to a keybinding of my choice:
(global-set-key (kbd "C-M-c") 'toggle-char-case-at-point)
The way this function operates is, after toggling the case it advances the point by one. So calling it repeatedly will toggle the cases of a sequence of chars. One could make it keep the point unchanged - that would require adding (backward-char) to the body.

Emacs ediff marked files in different dired buffers

I have the following function which runs ediff on the files I have marked in a dired buffer:
(defun mkm/ediff-marked-pair ()
"Run ediff-files on a pair of files marked in dired buffer"
(interactive)
(let ((marked-files (dired-get-marked-files nil)))
(if (not (= (length marked-files) 2))
(message "mark exactly 2 files")
(ediff-files (nth 0 marked-files)
(nth 1 marked-files)))))
It only works on files in the same directory, how could I make it work for files I mark in different dired directories?
Here is my solution, it works for files marked in the same dired buffer and also for files in different buffers.
(defun mkm/ediff-marked-pair ()
"Run ediff-files on a pair of files marked in dired buffer"
(interactive)
(let* ((marked-files (dired-get-marked-files nil nil))
(other-win (get-window-with-predicate
(lambda (window)
(with-current-buffer (window-buffer window)
(and (not (eq window (selected-window)))
(eq major-mode 'dired-mode))))))
(other-marked-files (and other-win
(with-current-buffer (window-buffer other-win)
(dired-get-marked-files nil)))))
(cond ((= (length marked-files) 2)
(ediff-files (nth 0 marked-files)
(nth 1 marked-files)))
((and (= (length marked-files) 1)
(= (length other-marked-files) 1))
(ediff-files (nth 0 marked-files)
(nth 0 other-marked-files)))
(t (error "mark exactly 2 files, at least 1 locally")))))
Augmenting mkm's answer a bit. In addition to working on 2 marked files potentially across dired buffers, it handles the case when there are 0 or 1 marked files. 0 marked files will use the file under the cursor as file A, and prompt for a file to compare with. 1 marked files will use the marked file as file A, and prompt for a file to compare with. The file under the point is used as the default in the prompt. I bound this to =.
(defun mkm/ediff-marked-pair ()
"Run ediff-files on a pair of files marked in dired buffer"
(interactive)
(let* ((marked-files (dired-get-marked-files nil nil))
(other-win (get-window-with-predicate
(lambda (window)
(with-current-buffer (window-buffer window)
(and (not (eq window (selected-window)))
(eq major-mode 'dired-mode))))))
(other-marked-files (and other-win
(with-current-buffer (window-buffer other-win)
(dired-get-marked-files nil)))))
(cond ((= (length marked-files) 2)
(ediff-files (nth 0 marked-files)
(nth 1 marked-files)))
((and (= (length marked-files) 1)
(= (length other-marked-files) 1))
(ediff-files (nth 0 marked-files)
(nth 0 other-marked-files)))
((= (length marked-files) 1)
(let ((single-file (nth 0 marked-files)))
(ediff-files single-file
(read-file-name
(format "Diff %s with: " single-file)
nil (m (if (string= single-file (dired-get-filename))
nil
(dired-get-filename))) t))))
(t (error "mark no more than 2 files")))))
Here's a solution:
(defvar mkm/dired-file-1)
(defun mkm/ediff-push ()
(interactive)
(setq mkm/dired-file-1 (dired-get-filename)))
(defun mkm/ediff-pop ()
(interactive)
(ediff-files mkm/dired-file-1 (dired-get-filename)))
(add-hook 'dired-mode-hook
(lambda()
(define-key dired-mode-map (kbd "C-c u") 'mkm/ediff-push)
(define-key dired-mode-map (kbd "C-c o") 'mkm/ediff-pop)))

Emacs23 cannot be transparent in Ubuntu(Gnome 3)

I search how to transparent my emacs window. But it doesn't work.
Something like this failed:
(global-set-key [(f8)] 'loop-alpha)
(setq alpha-list '((100 100) (95 65) (85 55) (75 45) (65 35)))
(defun loop-alpha ()
(interactive)
(let ((h (car alpha-list)))
((lambda (a ab)
(set-frame-parameter (selected-frame) 'alpha (list a ab))
(add-to-list 'default-frame-alist (cons 'alpha (list a ab)))
) (car h) (car (cdr h)))
(setq alpha-list (cdr (append alpha-list (list h))))
)
)
Here's a working implementation of what I think you were trying to do:
(global-set-key [(f8)] 'loop-alpha)
(defvar alpha-list '((100 100) (95 65) (85 55) (75 45) (65 35)))
(defun next-alpha ()
(let ((current-alpha
(or (frame-parameter (selected-frame) 'alpha)
(first alpha-list)))
(lst alpha-list))
(or (second
(catch 'alpha
(while lst
(when (equal (first lst) current-alpha)
(throw 'alpha lst))
(setf lst (cdr lst)))))
(first alpha-list))))
(defun loop-alpha ()
(interactive)
(let ((new-alpha (next-alpha))
(current-default (assoc 'alpha default-frame-alist)))
(set-frame-parameter (selected-frame) 'alpha new-alpha)
(if current-default
(setcdr current-default new-alpha)
(add-to-list 'default-frame-alist (cons 'alpha new-alpha)))))
Notice that any version you write that redefines alpha-list is going to behave very strangely with multiple frames. I would explain what was wrong with your code, but I honestly couldn't work out what it was supposed to do. Note that this would be somewhat easier to write if I allowed myself to (require 'cl) first, but I think this code should work - it does here at any rate!