Emacs: Set tab indent for just one file on the fly - emacs

I work on an open source project where the creator sets his tab-indents to 2 spaces.
I'd like to just enable it on the fly for the one file I work on and not other files of the same type. There must be something like M-x set-tab-indent. It is a JavaScript file ending in .js.
I know I can use:
(setq-default tab-width int)
inside my .emacs file, but I rather just call an M-x command to set it and forget it during my duration of working on this file. I tried M-x apropos and Google but couldn't find the specific command.
Thanks.

You can make the variable js-indent-level local to the buffer using:
M-x make-variable-buffer-local <RET> js-indent-level <RET>
Then you can set that variable in the buffer using:
M-x set-variable <RET> js-indent-level <RET> 2

The easiest way to do this for a single buffer is to use M-x set-variable.
Type M-x set-variable and press enter
When prompted for the variable to set, set tab-width then press enter
You'll be prompted with the line Set tab-width (buffer-local) to value:.
Put the value you want, then hit enter
The buffer should instantly be updated with the new value.

You could also use file local variables to automate omrib's solution for that one file, by adding this to it:
// Local Variables:
// js-indent-level: 2
// indent-tabs-mode: nil
// End:

Create a file ".dir-locals.el" in the project's directory and fill it like this:
((nil . ((tab-width . 2))))
This will take care of setting tab-width automatically and you don't have to modify the actual file (which is likely version-controlled.)
See the manual for more information about the format. I believe this requires Emacs 23.

As indicated by others, one issue with the File Local Variables approach is that you need to modify the file, and that's not ideal if you need to keep those declarations out of version control.
If you want the variables to apply to all files under a given directory, then Directory Local Variables is obviously the way to go, and you can implement that with either a .dir-locals.el file, or by calling (dir-locals-set-directory-class):
http://www.emacswiki.org/emacs/DirectoryVariables
http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html
I prefer the directory class approach myself, and I was thinking that it's a shame that there isn't an analogous approach for file local variables, but I found that the directory class code actually works perfectly with files, and the only issue is that dir-locals-set-directory-class calls file-name-as-directory on its argument, which prevents it from being matched, due to the trailing slash.
The following therefore is a way to configure directory local variables for a single file, without modifying the file itself, or affecting other files under the same parent directory.
(defun my-file-locals-set-directory-class (file class &optional mtime)
"Enable 'directory local' classes for individual files,
by allowing non-directories in `dir-locals-directory-cache'.
Adapted from `dir-locals-set-directory-class'."
(setq file (expand-file-name file))
(unless (assq class dir-locals-class-alist)
(error "No such class `%s'" (symbol-name class)))
(push (list file class mtime) dir-locals-directory-cache))
(dir-locals-set-class-variables
'my-javascript-class
'((nil . ((js-indent-level . 2)
(indent-tabs-mode . nil)))))
(my-file-locals-set-directory-class
"path/to/the/file.js" 'my-javascript-class)

I use a snippet of code in my init.el that tries to auto-detect files that use 2-space indents, and switch Emacs's indentation for that file to 2 spaces when it sees such files:
(add-hook 'js-mode-hook
(lambda ()
(when (string-match-p "^ [A-Za-z]" (buffer-string))
(make-variable-buffer-local 'js-indent-level)
(set-variable 'js-indent-level 2))))

Related

outline-minor-mode and org-mode

In emacs, org-mode has been enabled and have opened some *.org files. Now in the init.el file i am trying to enable the outline-minor-mode in order to fold the lines starting with ";" . When i try to evaluate the (outline-minor-mode) command i get the message "Symbol's function definition is void: th-outline-minor-mode-init"
Seems like the org-mode sets up the outline-minor-mode-hook
outline-minor-mode-hook's value is (th-outline-minor-mode-init)
This variable may be risky if used as a file-local variable.
How to setup the outline-minor-mode for init.el file so that the ";" is treated as heading.
Note:- When emacs is launched with --no-init-file option, outline-minor-mode works for init.el file
Doesn't org-mode use an org- prefix pretty consistently?
On that assumption, th-outline-minor-mode-init doesn't look like an org-mode function to me, so something else is probably at fault, and you'll need to find out what.
Obviously you can't find-function if it's void, so I'd just M-x rgrep your config for th-outline-minor-mode-init (or most likely searching for (add-hook 'outline-minor-mode-hook 'th-outline-minor-mode-init will find the culprit directly).
That issue aside, I happen to use outline-minor-mode in my init file (with headers being lines beginning with ;;;;, and auto-folding the ones beginning with ;;;; *), using the following Local Variables block at the end of the file:
;;; Local Variables:
;;; outline-regexp: ";;;; "
;;; eval:(progn (outline-minor-mode 1) (while (re-search-forward "^;;;; \\* " nil t) (outline-toggle-children)))
;;; End:
I keep a lot of documentation in the file, and with <backtab> bound to outline-toggle-children I find this a pretty convenient way to access it.

How to get Dired to ignore files with specific extensions

I put the following in my .emacs file:
(require 'dired-x)
(add-hook 'dired-load-hook '(lambda () (require 'dired-x)))
(setq dired-omit-files-p t)
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..+$\\|-t\\.tex$\\|-t\\.pdf$"))
But C-x d still shows me .pdf and .tex files. Did I get the syntax wrong in that last line?
Bonus question: Is there a way to get Dired to hide hidden directories, like .git folders?
A simple and very general solution which doesn't rely on any extras is to do C-u s to change the ls flags and immediately refresh (that is, C-u s takes care of refreshing also, so there is very little typing involved). Usually you will want to remove -a to hide dotfiles. But you can do everything you're already able to do in the shell console, which is far more than what a simple toggle mode could offer (at the cost of some extra keypressings). And there is a history of previous flags available, so "toggling" is pretty fast too.
Your regexp will match *-t.tex files, not *.tex ones.
With recent version of Emacs, it should be sufficient to add the following section to ~/.emacs to filter what you want:
(require 'dired-x)
(setq-default dired-omit-files-p t) ; this is buffer-local variable
(setq dired-omit-files
(concat dired-omit-files "\\|^\\..+$\\|\\.pdf$\\|\\.tex$"))
Update: by default, dired-omit-files regexp filters out special directories . and ... If you don't want this behavior, you can just override defaults (instead of inheriting them with concat):
(setq dired-omit-files "^\\.[^.]\\|\\.pdf$\\|\\.tex$")
The regexp ^\\.[^.] will match any string of length 2+ starting with a dot where second character is any character except the dot itself. It's not perfect (will not match filenames like "..foo"), but should be ok most of the time.

Load and evaluate file from .emacs

I work on many different machines and VMs, each of which might have their own needs regarding options for .emacs. I have a Git repository / subdirectory .common-system with a second Emacs Lisp file .common-system/emacs containing common definitions used for all my systems.
What changes can I make to .emacs which will load and eval my secondary definition file automagically? Bonus points for keeping the secondary file out of my buffer list after startup.
Have you tried:
(load-file ".common-system/emacs")
It works better (as Stefan suggests) if you specify the full path to the file, something like
(load-file "~/.common-system/emacs")
If you stick with you current repository layout, using load-file (as suggested by others) is the way to go.
However, if you name your top-level directory .emacs.d and place the file init.el in it, Emacs will find it and run it automatically. That way, you don't have to hand-edit a .emacs file on each system you use.
You use a (cond), dispatching on variables such as user-login-name, system-type and system-name
(cond
((equal user-login-name
"myname")
;; Stuff
)
((equal system-type 'gnu/linux)
(require 'some-file)
;; some-file, could be any file in load-path, named some-file.el, and ending
;; with (provide 'some-file)
))

emacs: open all .txt files in a specific directory in a specific major mode

EDIT: It turns out that the second edit to my .emacs file actually works. (See the comments below this entry.)
I tried a couple of addition to the .emacs to make all txt files opened in emacs use orgmode. They did not work. How can I make it happen?
;;SET EMACS AS DEFAULT MAJOR MODE TO FOR ALL FILES WITH AN UNSPECIFIED MODE
(setq default-major-mode 'org-mode)
;;OPEN ALL TXT FILES IN ORGMODE
(add-to-list 'auto-mode-alist '("\\.txt$" . org-mode))
Additionally:
It would be even better to open only txt files in a certain directory orgmode. Any hint as to how that could be done would also be appreciated.
Another way to do this is using directory-local variables. This is nice because you can put a file in any directory where you want this behavior to engage, and it works recursively in any subdirectories.
Create a file called .dir-locals.el in the desired directory.
Here are the contents:
((nil (eval . (if (string-match ".txt$" (buffer-file-name))(org-mode)))))
Read this like so: for any major-mode (nil), evaluate the following form:
(if .... (org-mode))
The regex in auto-mode-alist could be something more complex, like "^/path/to/.*\\.txt$"
You can implement a hook which verifies the file directory and modifies the buffer mode:
(add-hook 'find-file-hooks
(lambda ()
(let ((file (buffer-file-name)))
(when (and file (equal (file-name-directory file) "c:/temp/"))
(org-mode)))))
As an alternative you can add the mode line in the beginning of your text file. In this case emacs will set the specified mode.
; -*- mode: org;-*-
* header 1
** header 2
I glued together some code from Oleg Pavliv's answer here, and from yibe's at elisp - File extension hook in Emacs - Stack Overflow
(defun use-org-mode-for-dot-txt-files-in-owncloud ()
(when (and (string-match owncloud buffer-file-name)
(string-match "\\.txt\\'" buffer-file-name))
(org-mode)))
(add-hook 'find-file-hook 'use-org-mode-for-dot-txt-files-in-owncloud)
This way, though ownCloud Web and phone apps are currently friendly only with .txt files, from my PC I can use Emacs' Org-mode for them.
(If I set all .txt files to use Org-mode, it breaks todotxt-mode.)
(Note that owncloud is a string variable equal to my ownCloud path.)

How to make emacs stay in the current directory

When I start working on a project in emacs, I use M-x cd to get into the project root directory. But every time I use C-x C-f to open a file in one of the subdirectories (like app/model/Store.rb) emacs changes current directory to that of the file. Is there a way to make emacs stay at the root?
How about this? It replaces the regular find-file command with your own which always starts in some "root" directory (customize the find-file-root-dir variable):
(defvar find-file-root-dir "~/"
"Directory from which to start all find-file's")
(defun find-file-in-root ()
"Make find-file always start at some root directory."
(interactive)
(let ((default-directory find-file-root-dir))
(call-interactively 'find-file)))
(global-set-key (kbd "C-x C-f") 'find-file-in-root)
Assuming that you want the working directory of a file to be set to whatever the working directory was before you executed find-file, you could try the following:
(defmacro disallow-cd-in-function (fun)
"Prevent FUN (or any function that FUN calls) from changing directory."
`(defadvice ,fun (around dissallow-cd activate)
(let ((old-dir default-directory) ; Save old directory
(new-buf ad-do-it)) ; Capture new buffer
;; If FUN returns a buffer, operate in that buffer in addition
;; to current one.
(when (bufferp new-buf)
(set-buffer new-buf)
(setq default-directory old-dir))
;; Set default-directory in the current buffer
(setq default-directory old-dir))))
Armed with this macro, go search for operations that set the variable default-directory: M-x find-library files; M-x occur (setq default-directory. After some investigation, you discover that the desired function is called find-file-noselect-1. Also, it looks like set-visited-file-name is also a candidate. So:
(disallow-cd-in-function find-file-noselect-1)
(disallow-cd-in-function set-visited-file-name)
Note
Note that (disallow-cd-in-function find-file) would work just fine, but then if you switched to ido-mode, you'd be opening files with ido-find-file instead of find-file. Both of these functions ultimately use find-file-noselect-1, so hitting that with the macro is a more univeral solution.
Is there a way to make emacs stay at the root?
No, there isn't. C-x C-f always visits starting from the default directory of the buffer you are already vising. The default directory, by default, is the same directory as the file. You can change these (separately for every buffer) using M-x cd.
But that is not what you want. What you should do is C-x b to *scratch* (whose default directory is the same as where you launched Emacs from -- in your words "root"), and then visit a new file. And if you need to do this frequently, just open up a dired in there and work your way thru.
I appreciate I'm not answering your question directly, but I noticed you were more specific in your requirements in one of your comments: "I don't use compile or recompile, I just tend to close files I am not working on, since it takes fewer keystrokes to open a file again".
Have you got ido turned on for buffer switching? If you exclude the directory thing for a moment, switching files or buffers with ido is an identical number of keystrokes (C-x C-f vs C-x b, followed by a few characters in the file name). If you include the directory thing, switching files is more tricky for the precisely the reasons you mention. Sticking with buffers is much easier.
Going a step further, with the help of 'anything.el' it's quite easy to abstract away whether a given file is in a buffer or in a file using the file cache. For example, if you do the following:
(file-cache-add-directory-recursively "/my/ruby/project") ".*\\.rb$")
and run 'anything-for-files' (I have it bound to C-x f) all your open buffers are listed, along with all of the files you've just added to the file cache; isolating a given file usually only takes one or two more characters.
Any file in your project is thus 4 or 5 key presses away, and the directory they are in or whether or not they are in a buffer becomes irrelevant.
Hope that's helpful...
Sorry I haven't worked out the details, but you might be able to add a function to find-file-hook that resets the default directory to whatever you want.