Skip navigation

Tag Archives: dot-emacs

I just wanted to free a shortcut I had for “C-1” to let it behave the way it was meant with the command “digit-arguments”. This answer came in handy.

(global-unset-key (kbd “C-1”))
(define-key global-map (kbd “C-1”) ‘digit-argument)

By the way (a little tip) you can go: C-<digit ARG) instead of the C-u method; say to move 11 characters back, “C-11 C-b” is quicker than “C-u 11 C-b”, one less hit!

Now that I’m getting fond of using a heredoc to insert mysql scripts into the bash shell, have put this into my emacs initialization file. The same shortcut (Control+Shift+f11) will conveniently write different parameters depending in which shell I’m sitting in.

UPDATE: seems that I spoke too soon. Asking about the present working directory, formerly “(let ((a (shell-command-to-string “pwd | tr -d ‘\\n'”)))”, didn’t actually work when having opened shells of different servers via Tramp.
The correction below (less elegant) depends on the shell buffer being created/renamed with an identifiable name -which could be the hostname or whatever consistent nomenclature we choose-.
Anyway, until figuring a better way, this does the job of inserting the right parameters into each shell:

(defun my-heredoc-sql-invocation-from-shell ()
"Insert the appropiate parameters to run a heredoc mysql query depending on which shell I'm in"
  (let ((a (buffer-name (window-buffer (minibuffer-selected-window))))
        (b nil))
    (cond ((string-match "serverA" a) 
           (setq b "mysql -uroot mainDbToHitAt_A--password=`cat /etc/security/mysqlpassword` -t -vv <<\\!"))
          ((string-match "serverB" a) 
           (setq b "mysql -ualpha mainDbToHitAt_B --password=`cat /etc/security/mysqlpassword` -t -vv <<\\!"))
          ((string-match "serverC" a) 
           (setq b "mysql -uroot mainDbToHitAt_C  -t <<\\!")))
    (insert b)))

;; key shortcut to bind it to
(global-set-key (kbd "C-S-<f11>")  'my-heredoc-sql-invocation-from-shell)

Using an interactive shell in Emacs for Windows you might enconter a bug that causes the shell process to terminate when you signal and eof (See point 7.6 here)
If, for example, you try:

/Program Files/Emacs/ cat >newfile
this is a test file
being created with the cat command
directly from the user input 
in shell.

Now, by pressing C-d (or C-c C-d) the input should finish here, and the prompt return, but what happens instead, is that the shell process terminates. Same thing occurs if you try to M-x comint-send-eof or if you pick an eof signal from the menu.

I had noticed that before (in my Windows emac, only not under Unix), but last night I found that an eof sign could be generated by typing C-q C-z.

I choose to set an alias and bind it to some keys in my .emacs to overcome the issue:

(defalias 'eof
  (read-kbd-macro "C-q C-z RET"))
(global-set-key [M-S-f8] 'eof)

Of course a better solution would be to advice the comint-send-eof to procede accordingly when in emacs for Windows. Anybody knows how to do it, or mind to share a stronger fix than this hack? Any feedback will be appreciated.

Actually there’s no need to set an alias, as I learned that this is also possible and more straight-forward:

(global-set-key [(meta shift f8)] 
 '(lambda () (interactive) (execute-kbd-macro((read-kbd-macro "C-q C-z RET")))))

This was once the most important portion of elisp code I had put into my dot emacs.  Thanks to it I began to conciliate with the editor which I sort of resisted at first, by finding it foreign to my habits and liking. I was accustomed to the way Dreamveaver handled the indenting of selected text in blocks, so getting emacs to behave in such familiar and practical style was critical to ease the experience of using it in a daily basis -as I needed  a couple of years ago when entering a new position.

Pretty soon I saw why emacs was so superior in regard of its extensibility: with basic elisp knowledge, the help of this discussion and a few lines of code tweaked I was able to get indent/unindent function the way I wanted. Now to select text as a block, I not longer needed to set the mark and point exactly from the beginning to the end of a line or group of lines. The code conveniently extended the highlighted area via the tab key, turning the sub-selection into a block containing all the text of the line(s) involved.

Besides, the selection was configured so to not disappear unless you click outside it, that is, while keeping  pressed the tab (or Shift-tab) key(s) you could get the text to shift continuously right (or left).

Having bound the tab key with the indentation functions required a few adjustment to make it context-sensitive. Here is how the tab key behaves after the changes:

  • First, to insert a real tab space, (when the cursor is before a word), you need to use Ctrl -q-tab.
  • If the text point is, at least, a space away from the end of a word, a standard tab-space is inserted.
  • If the text point is exactly at the end of a word, the tab uses the hippie-expand function to auto-complete the word. If Shift+tab are used instead, words are deleted backward one at a time up to the beginning of the line.
  • When editing in org-mode an exception was set to respect its visibility cycling function (org-mode cleverly uses the tab key to rotate the current state of tree and sub-trees).

Finally, Mac and PC users would probably appreciate the added function that makes Shift + click to end a selection of text, which is the default way on both platforms (I grabbed it here, from Dave Peck).

So, as you can see, the whole point of the code below is to ease the manual indentation of code. Not being comfortable with the automatic indentation in emacs, I like to avoid it at times, or for certain modes. Check the associated hack posted on how to deactivate it.

Please, have a look at the elisp lines. Remember that you could copy and paste all into the scratch buffer and do “M-x evaluate-buffer” to get them immediately working.

;; turn on transient mark mode
;;(that is, we highlight the selected text)
(transient-mark-mode t)

(setq my-tab-width 2)

(defun indent-block()
  (shift-region my-tab-width)
  (setq deactivate-mark nil))

(defun unindent-block()
  (shift-region (- my-tab-width))
  (setq deactivate-mark nil))

(defun shift-region(numcols)
" my trick to expand the region to the beginning and end of the area selected
 much in the handy way I liked in the Dreamweaver editor."
  (if (< (point)(mark))
    (if (not(bolp))    (progn (beginning-of-line)(exchange-point-and-mark) (end-of-line)))
    (progn (end-of-line)(exchange-point-and-mark)(beginning-of-line)))
  (setq region-start (region-beginning))
  (setq region-finish (region-end))
    (if (< (point) (mark)) (exchange-point-and-mark))
    (let ((save-mark (mark)))
      (indent-rigidly region-start region-finish numcols))))

(defun indent-or-complete ()
  "Indent region selected as a block; if no selection present either indent according to mode,
or expand the word preceding point. "
  (if  mark-active
    (if (looking-at "\\>")
  (hippie-expand nil)
      (insert "\t"))))

(defun my-unindent()
  "Unindent line, or block if it's a region selected.
When pressing Shift+tab, erase words backward (one at a time) up to the beginning of line.
Now it correctly stops at the beginning of the line when the pointer is at the first char of an indented line. Before the command would (unconveniently)  kill all the white spaces, as well as the last word of the previous line."

  (if mark-active
        (if (looking-back "^[ \t]*")
              ;;"a" holds how many spaces are there to the beginning of the line
              (let ((a (length(buffer-substring-no-properties (point-at-bol) (point)))))
                  ;; delete backwards progressively in my-tab-width steps, but without going further of the beginning of line.
                  (if (> a my-tab-width)
                      (delete-backward-char my-tab-width)
                    (backward-delete-char a)))))
          ;; delete tab and spaces first, if at least 2 exist, before removing words
            (if(looking-back "[ \t]\\{2,\\}")
              (backward-kill-word 1))))))))

(add-hook 'find-file-hooks (function (lambda ()
 (unless (eq major-mode 'org-mode)
(local-set-key (kbd "<tab>") 'indent-or-complete)))))

(if (not (eq  major-mode 'org-mode))
      (define-key global-map "\t" 'indent-or-complete) ;; with this you have to force tab (C-q-tab) to insert a tab after a word
      (define-key global-map [S-tab] 'my-unindent)
      (define-key global-map [C-S-tab] 'my-unindent)))

;; mac and pc users would like selecting text this way
(defun dave-shift-mouse-select (event)
 "Set the mark and then move point to the position clicked on with
 the mouse. This should be bound to a mouse click event type."
 (interactive "e")
 (mouse-minibuffer-check event)
 (if mark-active (exchange-point-and-mark))
 (set-mark-command nil)
 ;; Use event-end in case called from mouse-drag-region.
 ;; If EVENT is a click, event-end and event-start give same value.
 (posn-set-point (event-end event)))

;; be aware that this overrides the function for picking a font. you can still call the command
;; directly from the minibufer doing: "M-x mouse-set-font"
(define-key global-map [S-down-mouse-1] 'dave-shift-mouse-select)

;; to use in into emacs for  unix I  needed this instead
; define-key global-map [S-mouse-1] 'dave-shift-mouse-select)

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; this final line is only necessary to escape the *scratch* fundamental-mode
;; and let this demonstration work

I revised the code and modified some things. Especially the function ‘my-unindent” in order to add some sophistication on how the shifting backwards now occurs. The main improvement is that deleting backwards will never lead to jumping to the previous line (and removing words from there) . Here’s how the movement to left is done when pressing Shift + tab:

  • killing word by word, if the insertion point is at the right of any text.
  • stepping back, in increments (set by the variable my-tab-width), BUT ALWAYS stopping at the beginning of the line when the cursor is at the left of any indented text.

You can see how much simpler the function looked before I decided to better it:

(defun my-unindent()
  "Unindent line, or block if it's a region selected"
  (if mark-active
    (if(not(bolp))(delete-backward-char 2 ))))

Having discovered that C-i means “tab” (remember that in this setup, tab is associated with the function ‘indent-or-complete) I’m changing “M-i”, to act the same as “Shift-tab” does.
Might come as a good alternative, one supposed to be less stressful on the wrists.
(“Meta + i” comes originally bound to ‘tab-to-tab-stop)

(global-set-key (kbd "M-i") 'my-unindent)

In emacs you use the function “occur” to find all occurrences of a string (or regexp) in a buffer. The matching lines are listed in another buffer named “*Occur*”, and you can click them there to navigate to the corresponding lines in the original buffer. That is, buffer ‘*Occur*’ acts as a hypertext index to your buffer.

Here’s a little bit of elisp that I wrote inside the dot emacs (the configuration to customize stuff) to re-define occur (well it’s actually a sort of wrapper of the function since itself isn’t touched and you can still call it with M-x occur ).

As the code is already commented, I’ll put it here without much explanation.

(defun my-occur (&optional arg)
 "Make sure to always put occur in a vertical split, into a narrower buffer at the side.
I didn't like the default horizontal split, nor the way it messes up the arrangement of windows in the frame or 
the way in which the standard way uses a neighbor window."
  (interactive "P")
  (window-configuration-to-register ?y) ; store whatever frame configuratin we are currently in
  (occur (read-from-minibuffer "Regexp: "))
  (if (occur-check-existence)
        (enlarge-window-horizontally -10)
        (set-cursor-color "green")))

(defun occur-procede-accordingly ()
  "Switch to occur buffer or prevent opening of the occur window if no matches occured."
  (interactive "P")
  (if (not(get-buffer "*Occur*"))
      (message "There are no results.")
    (switch-to-buffer "*Occur*")))

(defun occur-check-existence()
  "Signal the existance of an occur buffer depending on the number of matches."
  (if (not(get-buffer "*Occur*"))

(define-key global-map (kbd "C-S-o") 'my-occur)

(defun occur-mode-quit ()
  "Quit and close occur window. I want to press 'q' and leave things as they were before in regard of the split of windows in the frame.
This is the equivalent of pressing C-x 0 and reset windows in the frame, in whatever way they were,
plus jumping to the latest position of the cursor which might have been changed by using the links out
of any of the matches found in occur."
  (switch-to-buffer "*Occur*")
  ;; in order to know where we put the cursor thay might have jumped from qoccur
  (other-window 1)                  ;; go to the main window
  (point-to-register ?1)            ;; store the latest cursor position
  (switch-to-buffer "*Occur*")      ;; go back to the occur window
  (kill-buffer "*Occur*")           ;; delete it
  (jump-to-register ?y)             ;; reset the original frame state
  (set-cursor-color "rgb:ff/fb/53") ;; reset cursor color
  (register-to-point ?1))           ;; re-position cursor

;; some key bindings defined below. Use "p" ans "n" as in dired mode (without Cntrl key) for previous and next line; just show occurrence without leaving the "occur" buffer; use RET to display the line of the given occurrence, instead of jumping to i,t which you do clicking instead;  also quit mode with Ctrl-g.
(define-key occur-mode-map (kbd "q") 'occur-mode-quit)
(define-key occur-mode-map (kbd "C-q") 'occur-mode-quit)
(define-key occur-mode-map (kbd "C-g") 'occur-mode-quit)
(define-key occur-mode-map (kbd "C-RET") 'occur-mode-goto-occurrence-other-window)
(define-key occur-mode-map (kbd "C-<up>") 'occur-mode-goto-occurrence-other-window)
(define-key occur-mode-map (kbd "RET") 'occur-mode-display-occurrence)
(define-key occur-mode-map (kbd "p") 'previous-line)
(define-key occur-mode-map (kbd "n") 'next-line)