Showing posts with label emacs. Show all posts
Showing posts with label emacs. Show all posts

Saturday, December 02, 2023

Cycle Through Emacs Themes

I wrote a library that lets you cycle through the available themes in Emacs. F10 and shift-F10 keys will cycle forward and backward through the themes. The theme name is printed for reference.

https://github.com/tsengf/theme-cycle

Installation
Download theme-cycle.el into ~/.emacs.d.

Add the following to your Emacs configuration

(add-to-list 'load-path (expand-file-name "~/.emacs.d)
(require 'theme-cycle)
;; Load as many themes as you are interested in exploring.
(use-package doom-themes)
(use-package ef-themes)
(use-package modus-themes)
(use-package solarized-themes)

To Use

Use F10 to cycle forward through the themes. Use shift-F10 to cycle backward through the themes.


Monday, November 27, 2023

Preventing Emacs Window Resizing on Startup

If you set the geometry of your Emacs window in elisp, you may find that the window redraws itself upon resizing. Note that I try to avoid using Xresources to set the geometry which is another solution to this problem. I'd like to control all of my settings in Emacs elisp.

To do this, we will replace default-frame-alist by setting it in the set-initial-frame function which will be associated with the before-init-hook. This hook is run before the frame is drawn preventing the window to resize.

In this example, I set the font to RobotoMono. The width is 170 characters wide and the height is y resolution of the screen less 200 pixels. I also disable other parts of the window like the menu bar, tool bar, and scroll bars.

It would be great if I can control the default background color before my theme kicks in.

(defun set-initial-frame ()
  "Defines and center the frame window"
  (let* ((width-chars 170)
         (height-buffer 200)
         (setq my-font "RobotoMono Nerd Font")
         (monitor-width (x-display-pixel-width))
         (monitor-height (- (x-display-pixel-height) height-buffer)))
    (setq default-frame-alist
          `((width . ,width-chars)
            (height . (text-pixels . ,monitor-height))
            (font . ,my-font)
            ;; Prevent the glimpse of un-styled Emacs by disabling these UI elements early.
            (menu-bar-lines . 0)
            (tool-bar-lines . 0)
            (horizontal-scroll-bars . nil)
            (vertical-scroll-bars . nil)))))

(add-hook 'before-init-hook #'set-initial-frame)

Sunday, November 19, 2023

Using use-package to bootstrap quelpa and quelpa-use-package

I use use-package and wanted to use it to bootstrap quelpa and loading quelpa-use-package. The project pages had instructions without use-package. Here is what I had to do.

(require 'package)
(setq package-archives
      '(("melpa" . "https://melpa.org/packages/"))
      use-package-always-ensure t)

(package-initialize)

(require 'use-package-ensure)

(use-package quelpa
  :ensure)

(use-package quelpa-use-package
  :demand
  :config
  (quelpa-use-package-activate-advice))

;; Now, you can take advantage of the :quelpa keyword.
(use-package copilot
  :quelpa (copilot :fetcher github
                   :repo "zerolfx/copilot.el"
                   :branch "main"
                   :files ("dist" "*.el"))
  :hook (prog-mode . copilot-mode)
  :bind (:map copilot-completion-map
              ("<tab>" . copilot-accept-completion)))

Thursday, October 03, 2019

Fast Scrolling in Emacs

I work with some files that have some complex fontification rules. There is a significant lag when scrolling quickly through these files. Although I am using jit-lock-mode as my font-lock-support-mode, the lag is unbearable. One solution to this is to use fast-scroll. https://github.com/ahungry/fast-scroll. fast-scroll temporarily disables font-lock when scrolling. This has worked out nicely for me.

Sunday, June 04, 2017

Launch Emacs for Windows with Batch File using Emacs Configuration from Cygwin

I maintain a shared Emacs configuration under Linux and Cygwin. In Windows, I wanted to easily launch Emacs from the Desktop with the following goals.

  • Create a shortcut in the taskbar that launches Emacs for Windows
  • Have Emacs for Windows obey the Emacs configuration from Cygwin
  • Avoid opening extra console windows

Some prerequisites,


I created a file called c:\cygwin64\emacs.bat with the following contents.
c:\cygwin64\bin\run bash.exe -c ~/dotfiles/bin/emacs.sh

The file ~/dotfiles/bin/emacs.sh is a shell script that sits in my Cygwin directory. It is a wrapper script that calls Emacs for Windows if I'm running Cygwin.

It is assumed that the default Emacs configuration sits in the ~/.emacs file under Cygwin.

Pin the c:\cygwin64\emacs.bat script to your task bar. See below if you do not know how to do this. Clicking on it will open Emacs for Windows without any intervening console windows.

References

Saturday, November 10, 2012

Slow scrolling speed in Emacs

When a large buffer is open which requires fontification, you may notice that continuous scrolling becomes choppy. Fontification by default is not deferred and takes place immediately. This causes the fontification of large buffers to slow down the act of scrolling. The effect is magnified when the size of the Emacs window is increased. To address this problem, defer fontification by setting an idle time after which deferred fontification should take place. Add the following code to your .emacs file. You can tweak the value to suit your system requirements.

(setq jit-lock-defer-time 0.05)

Friday, July 01, 2011

Automatically byte compile your Emacs configuration file

I like the ability to automatically byte compile my .emacs file but never had Emacs behave in a way that was acceptable to me. In particular, the interaction between debugging a .emacs file and automatic byte compile sometimes is troublesome. The solution for me which is least bad is to automatically byte compile on save of the .emacs buffer. To do this, add the following code to your .emacs.

(defun auto-recompile-emacs-file ()
  (interactive)
  (when (and buffer-file-name (string-match "\\.emacs" buffer-file-name))
    (let ((byte-file (concat buffer-file-name "\\.elc")))
      (if (or (not (file-exists-p byte-file))
              (file-newer-than-file-p buffer-file-name byte-file))
          (byte-compile-file buffer-file-name)))))

(add-hook 'after-save-hook 'auto-recompile-emacs-file)

Sam Morar suggests a more general solution of automatically compiling after saving a lisp-mode buffer.

(add-hook 'emacs-lisp-mode-hook '(lambda ()
  (add-hook 'after-save-hook 'emacs-lisp-byte-compile t t))
)

Michael Hoffman points out that one might not want to compile all lisp files. His suggestion is to compile only if a corresponding .elc file already exists.

Tuesday, June 28, 2011

Distinguish buffers of the same filename in Emacs

Have you ever opened multiple files of the same name only to find you can't tell which buffer holds which file? By default, Emacs adds a <number> postfix to the name of subsequent buffers opened which has the same filename as the filename of a preexisting buffer. Sometimes, it is not convenient to remember which postfix tag goes with which file. The solution is to use Uniquify. Uniquify postfixes the buffer name with the directory name of the file. Add the following to your .emacs file.
(require 'uniquify)
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)
You can customize uniquify-buffer-name-style. Read more with C-h-v uniquify-buffer-name-style.

Sunday, June 26, 2011

Remember the last cursor position in Emacs

It is often always useful to have Emacs remember the last cursor position of a file that you had opened. Add the following code to your .emacs file to accomplish this.

(setq save-place-file "~/.emacs.d/saveplace")
(setq-default save-place t)
(require 'saveplace)

The save-place-file variable identifies the file location where the cursor position information is kept. I like to keep my home directory clean of unnecessary files so I have defined it to ~/.emacs.d/saveplace.

Thursday, June 23, 2011

Setting up Cedet for multiple copies of the same project in Emacs

When working on a project from a project repository, I find it useful to have multiple copies of a project checked out at once. I use Cedet and it is repetitious to define a project for each checked-out copy. My solution is to utilize an environment variable called PROJECT_WORKSPACES containing the space-separated paths of all checked-out copies. The following .emacs code sets up the Cedet project for each of project paths specified in the environment variable.

  (when (getenv "PROJECT_WORKSPACES")
    (setq project_paths (split-string (getenv "PROJECT_WORKSPACES")))

    (while project_paths
      (setq project_path (eval (car project_paths)))
      (when (and project_path (file-exists-p project_path))
        (ede-cpp-root-project project_path
                              :name project_path
                              :file (concat project_path "/p4config.txt")
                              :include-path '("/include"
                                              )
                              ))
      (setq project_paths (cdr project_paths))
      )
    )

More idiomatic version by Aankhen.

(when (getenv "PROJECT_WORKSPACES")
   (let ((paths (split-string (getenv "PROJECT_WORKSPACES"))))
     (dolist (path paths)
       (when (and path (file-exists-p path))
         (ede-cpp-root-project path
                               :name path
                               :file (concat path "/p4config.txt")
                               :include-path '("/include"))))))

Tuesday, June 21, 2011

Cscope output window line wraps in Emacs

As mentioned in a previous post, I often find it useful to disable line wrapping. Unfortunately, if you use cscope in Emacs, you will notice that it doesn't obey the default truncate-lines setting. Search results are wraped making parsing with a eye slightly more cumbersome. To disable the line wraps, add the following code to your .emacs file.
(setq cscope-truncate-lines t)

Sunday, June 19, 2011

Confirm to quit when editing files from a project in Emacs

You have many files loaded in Emacs. You are typing at warp speed. All of a sudden, you attempt to save, but accidentally press the sequence of keys that exits Emacs. You realize this but it's too late. The Emacs window disappears.

To get around this problem, I wrote a function that tries to determine if I am working on a software project. If so, a yes or no confirmation will be issued prior to exiting. If not, no confirmation will be issued prior to exiting. All my projects are located in a parent directory called projects. Hence, it is simple enough to search for the string "projects" in the buffer list. If the string is found, introduce a yes or no confirmation. Add the following code to your .emacs file.

(defun have-projects-buffer ()
  "Search for buffers that come from the projects directory and return t if found else nil."
  (interactive)
  (defvar list (buffer-list))
  (defvar found nil)
  (while list
    (defvar element (car list))                      
    (when element
      (defvar file-name (buffer-file-name element))
      (if file-name
          (progn
            (if (string-match "projects" file-name)
                (setq found t)))))
    (setq list (cdr list)))
  found)

(defun my-quit-hook ()
  "Ask if the user really wants to quit Emacs."
  (interactive)
  (if (have-projects-buffer)
      (y-or-n-p "Really quit Emacs? ")
    t))

(add-hook 'kill-emacs-query-functions 'my-quit-hook)

Thanks Jürgen for the suggestions. Here is a cleaner version.

(defun have-projects-buffer ()
  (delq nil (mapcar (lambda (buf1)
                      (string-match "projects" buf1))
                    (delq nil (mapcar (lambda (buf2)
                                        (buffer-file-name buf2))
                                      (buffer-list))))))


Raimon Grau at puntoblogspot has some different approaches to solving this problem.

Cleaner versions with and without using Common Lisp.

(require 'cl)
(defun project-buffers-p ()
  (some (lambda (buf)
          (let ((file (buffer-file-name buf)))
            (when file
              (string-match "projects" file))))
        (buffer-list)))

(defun project-buffers-p ()
  (not (null (delq nil (mapcar (lambda (buf)
          (let ((file (buffer-file-name buf)))
            (when file
              (string-match "projects" file))))
        (buffer-list))))))

Shorter version suggested at blog.tapoueh.org.

(require 'cl)
(defun project-buffers-p ()
  (loop for b being the buffers
        when (string-match "projects" (or (buffer-file-name b) ""))
        return t))

Saturday, June 18, 2011

Scroll up and down line by line in Emacs

It is sometimes useful to align a particular line in your buffer in your Emacs window. Rather than moving the cursor and recentering the buffer around your cursor, this is more easily done if you can simply scroll the text. Add the following code to your .emacs file and use Ctrl-, and Ctrl-. to scroll up or down one line at a time.

(defun scroll-up-one-line()
  (interactive)
  (scroll-up 1))

(defun scroll-down-one-line()
  (interactive)
  (scroll-down 1))

(global-set-key [?\C-.] 'scroll-down-one-line)
(global-set-key [?\C-,] 'scroll-up-one-line)

Friday, June 17, 2011

Prevent accidental iconify of Emacs

It is sometimes the case that you may accidentally press Ctrl-z while in Emacs and the Emacs Window magically disappears. Ctrl-z is by default bound to iconify-frame which is another way of saying minimize the window. To make this feature more pleasant, introduce a yes or no confirmation when Ctrl-z is pressed. Add the following code to your .emacs file.

(defun smart-iconify-or-deiconify-frame()
  (interactive)
  (if (yes-or-no-p (format "Are you sure you want to iconify/deiconify Emacs? "))
      (iconify-frame))
  )

(global-set-key [?\C-z] 'smart-iconify-or-deiconify-frame)

Thursday, June 16, 2011

Open files and switch buffers with less effort in Emacs

Enabling ido mode makes opening files and switching buffers a little more descriptive by lising all the possible completions in the minibuffer. It also makes editing the path of a file more speedy. For example, pressing the backspace to delete a directory name deletes the entire directory name rather than a single character of the directory name. This will require some practice but once you are comfortable, ido is a powerful tool. If ido is being too smart and you want to temporary disable it, simply press Ctrl-f. This will revert to the traditional minibuffer behavior for specifying file and buffer names. Add the following code to your .emacs file to enable ido mode.

(when (fboundp 'ido-mode)
  (ido-mode t)
  (setq ido-save-directory-list-file nil)
  )

Enable horizontal scrolling in Emacs

When dealing with lines longer than the window width, the default behavior of Emacs is to wrap lines. It can be useful to disable this feature. Add the following to your .emacs file to truncate long lines and display only the part of the line that is in the window. The conditional makes this work in Emacs 23 as well as older versions of Emacs.

;; horizontal scrolling
(if (boundp 'truncate-lines)
    (setq-default truncate-lines t) ; always truncate
  (progn
    (hscroll-global-mode t)
    (setq hscroll-margin 1)
    (setq auto-hscroll-mode 1)
    (setq automatic-hscrolling t)
   ))

Monday, June 13, 2011

Bind F5 to revert-buffer in Emacs

I use F5 as the revert key in Emacs. Add the following code to your .emacs file to accomplish to bind F5 to the revert-buffer function.

(global-set-key [f5] '(lambda () (interactive) (revert-buffer nil t nil)))

Sunday, June 12, 2011

Semantic-ia-fast-jump doesn't push the tag mark in Emacs

In Emacs 23.3, if you try to run pop-tag-mark after performing semantic-complete-jump, you will get the message "The tags stack is empty." The reason for this behavior is because the function push-tag-mark is not defined in etags.el. This behavior is inconsistent with the behavior of find-tag which does push the tag mark. To get around this problem, define the push-tag-mark function by adding the following code to your .emacs file.

;; Implementing my own copy of this function since it is required by
;; semantic-ia-fast-jump but this function is not defined in etags.el
;; of GNU emacs
(require 'etags)
(unless (fboundp 'push-tag-mark)
  (defun push-tag-mark ()
    "Push the current position to the ring of markers so that
    \\[pop-tag-mark] can be used to come back to current position."
    (interactive)
    (ring-insert find-tag-marker-ring (point-marker))
    )
  )

Friday, June 10, 2011

Disable byte-compile warnings in Emacs

In Emacs, it is common to get warnings when byte compiling an elisp file. To suppress these warnings, add the following snippit of code to your Emacs configuration file. Thanks Aankhen for the correction.

;; ignore byte-compile warnings
(setq byte-compile-warnings '(not nresolved
                                  free-vars
                                  callargs
                                  redefine
                                  obsolete
                                  noruntime
                                  cl-functions
                                  interactive-only
                                  ))

Sunday, June 05, 2011

Set the title of your Emacs window to the current file being edited

You can set the title of your Emacs window to the name of the file being edited. Add the following code to your .emacs file. Note, I run Emacs from within Cygwin where the HOME environment variable uses double backslashes as path separators, and the buffer-file-name uses slashes as path separators. The regular expression replacement below performs the conversion from backslashes to slashes.

(setq frame-title-format
      '(:eval
        (if buffer-file-name
            (replace-regexp-in-string
             (replace-regexp-in-string "\\\\" "/" (getenv "HOME")) "~"
             (concat (file-name-directory buffer-file-name) "%b"))
          (buffer-name)
          )))