When writing executable scripts, and declarative configuration files that use a common language (eg. Python), I often find it undesirable to add an extension to the file name. Many syntax-highlighting text editor (eg. Geany) are subsequently unable to automatically determine the filetype.
Is there any standard method for indicating to editors the type of source in the file?
Vim
Vim has a concept called a modeline. A modeline is a specially formatted line either withinin the first or last 5 lines of the textfile, which allows you to :setlocal local variables. For example, for C:
/* vi: set filetype=c fileencoding=UTF-8 shiftwidth=4 tabstop=4 expandtab */
or Ruby:
# vi: set filetype=ruby fileencoding=UTF-8 shiftwidth=2 tabstop=2 expandtab
Some more documentation.
Emacs
Emacs has a similar concept, called File Variables.
File Variables are either specified at the beginning of the file (in the first line, or if there is a shebang line, then in the second) in this form:
/* *-* mode: cc c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil *-* */
or at the end:
# Local Variables:
# mode: ruby
# coding: utf-8
# c-basic-offset: 2
# tab-width: 2
# indent-tabs-mode: nil
# End:
jEdit
jEdit calls this buffer-local properties. The have to sit within the first or last 10 lines and look like this:
# :mode=ruby:indentSize=2:tabSize=2:noTabs=true:
jEdit also uses the shebang line as a fallback for mode detection.
Komodo Edit
There is a plugin called Komode (pun intended) which adds modeline support to Komodo Edit:
# komode: le=unix language=ruby codepage=utf8 tab=2 notabs indent=2
It also understands a limited subset of Vim modelines.
Others
A lot of other editors also have either their own variants of this, or support one of the above (usually Vim).
Python / Ruby encoding
Both Ruby 1.9 and Python require that the encoding for non-ASCII source files be explicitly specified. Fortunately, they do this in a way that is compatible with both Emacs and Vim modelines. (Basically, they look for the string coding followed by a non-word character followed by whitespace followed by a valid encoding name. Both Vim's fileencoding= and Emacs' coding: satisfy these requirements.)
Modeline Generator
Here is a simple modeline generator, which generates modelines for Vim, Emacs and jEdit.
Typically the shebang line is used as a fall-back.
For example, a Ruby script without an extension would begin with:
#!/usr/bin/env ruby
This works for many editors if you're using non-standard shebangs:
#!/usr/bin/env python3
# filetype=python
Related
I have a config file under my python project, called "logging.conf", the file looks like:
[formatters]
keys: console, logging
[formatter_console]
format: %(asctime)s | %(message)s
[formatter_logging]
format: %(message)s
etc etc etc
Tried :syntax on, nothing happened, the .conf files look very plain. Is there anyway I can turn on some syntax to make the .conf file more colorful and readable?
You can check vim.org or the Internet for a suitable syntax.
As a first approximation, this somewhat looks like DOS / Windows INI files. Vim comes with a syntax for them; try
:setf dosini
If that suits you, you can add a filetype detection rule:
:autocmd BufRead,BufNewFile logging.conf setf dosini
See :help ftdetect for details.
Your file looks plain, it is correct. ( I assume that you have already set conf as the filetype of your current buffer :set ft? to verify).
if you check your $VIMRUNTIME/syntax/conf.vim
you will see, there are three different colors will be shown in a conf file:
hi comment, lines starting with #
hi string, text wrapped by ' or "
and normal text
your current text has no comment, no quoted text. so it shows just in one color.
The file you show (python conf) is actually ini structure. try Ingo's answer.
I almost have that kind of text style but mine was the ansible hosts file, I found a lot of options here filetype.vim. I used povini or texmf for my ansible hosts file text highlights
To configure it in your .vimrc.
Grab the string before setf, so in case of provini, it is au BufNewFile,BufRead .povrayrc
Replace the last string(.povrayrc) with *.conf
The final config is au BufNewFile,BufRead *.conf for your .vimrc
The key issue here is that the syntax in your conf file is usually associated with .ini files. Setting the type (ingo's answer) fixes this issue. Alternatively you could just rename your file.
mv logging.conf logging.ini
echo "syntax on" >> ~/.vimrc
Setting .ini as the file extension maybe more desirable than having custom rules. (I do understand that this may not be possible in all cases)
I'm on a system (linux) that always recognizes cpp files (*.cc) as tcl files. I don't know what file type that is, but I wanted to override it. The correct syntax highlighting is chosen if I manually do :set ft=cpp. However, I'm having troubles setting that automatically and I don't want to use the modeline option. My own .vimrc doesn't interfere (same result if I rename it).
From the vim help (:help ftplugin-override)
*ftplugin-overrule*
If a global filetype plugin does not do exactly what you want, there are three
ways to change this:
1. Add a few settings.
You must create a new filetype plugin in a directory early in
'runtimepath'. For Unix, for example you could use this file:
vim ~/.vim/ftplugin/fortran.vim
You can set those settings and mappings that you would like to add. Note
that the global plugin will be loaded after this, it may overrule the
settings that you do here. If this is the case, you need to use one of the
following two methods.
I have used this option before on another machine and that worked. I've tried
<file> .vim/ftplugin/tcl.vim
set filetype=cpp
"au BufRead,BufNewFile * set filetype=cpp
The first line correctly sets the filetype (:set ft? returns cpp), but syntax highlighting is not the same as if I said :set ft=cpp. It's still the tcl syntax highlighting. The second line does nothing.
2. Make a copy of the plugin and change it.
You must put the copy in a directory early in 'runtimepath'. For Unix, for
example, you could do this:
cp $VIMRUNTIME/ftplugin/fortran.vim ~/.vim/ftplugin/fortran.vim
Then you can edit the copied file to your liking. Since the b:did_ftplugin
variable will be set, the global plugin will not be loaded.
A disadvantage of this method is that when the distributed plugin gets
improved, you will have to copy and modify it again.
There seems to be no file in my $VIMRUNTIME directory /usr/share/vim/vim72/ftplugin/ called tcl.vim.
3. Overrule the settings after loading the global plugin.
You must create a new filetype plugin in a directory from the end of
'runtimepath'. For Unix, for example, you could use this file:
vim ~/.vim/after/ftplugin/fortran.vim
In this file you can change just those settings that you want to change.
Has the same effect as 1. Is there anything else I can try? Thanks a lot in advance.
cpp is the default filetype for *.cc and *.cpp files.
The tcl filetype is only set for *.tcl, *.tk, *.itcl, *.itk and *.jacl.
I see no reason why Vim would default to tcl when loading a *.cc file but you could check if theses files are installed:
/usr/share/vim/vim7x/ftplugin/cpp.vim
/usr/share/vim/vim7x/indent/cpp.vim
/usr/share/vim/vim7x/syntax/cpp.vim
and if the correct checks are done in:
/usr/shhare/vim/vim7x/filetype.vim
Are you the only person working on this machine? Do you use modelines?
I heard that we can specify VIM indent for a file by embedding the indentation commands into the file to be edited.
Can somebody let me know how to do this?
The thing you are looking for is called a modeline.
Here is a modeline that I commonly use for vim:
/* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: */
A similar thing for emacs would look like this:
/* -*- Mode: tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
This question has been covered before though.
Something like
// vim: set ts=4 sw=4 et:
where // is your language's comment marker.
You can also specify indentation for a given filetype.
For example for python files, you can add this line to your .vimrc file:
autocmd FileType python set sw=4 sta
The advantage compared to modelines is that you don't have to write it everytime. Then for a specific python file, if you want to change the indentation, you can write this modeline:
# vim: set sw=2:
My Vim editor auto highlights PHP files (vim file.php), HTML files (vim file.html) and so on.
But when I type: vim file and inside it write a Bash script, it doesn't highlight it.
How can I tell Vim to highlight it as a Bash script?
I start typing #!/bin/bash at the top of the file, but it doesn't make it work.
Are you correctly giving the shell script a .sh extension? Vim's automatic syntax selection is almost completely based on file name (extension) detection. If a file doesn't have a syntax set (or is the wrong syntax), Vim won't automatically change to the correct syntax just because you started typing a script in a given language.
As a temporary workaround, the command :set syn=sh will turn on shell-script syntax highlighting.
The answers so far are correct that you can use the extension (like .sh) or a shebang line (like #!/bin/bash) to identify the file type. If you don't have one of those, you can still specify the file type manually by using a modeline comment at the top or bottom of your file.
For instance, if you want to identify a script without an extension as a shell script, you could add this comment to the top of your file:
# vim: set filetype=sh :
or
# vim: filetype=sh
That will tell vim to treat the file as a shell script. (You can set other things in the modeline, too. In vim type :help modeline for more info.)
Actually syntax highlighting is a feature of vim not vi.
Try using vim command and then do
:syntax on.
I came to this answer looking for specifically how to highlight bash syntax, not POSIX shell. Simply doing a set ft=sh (or equivalent) will result in the file being highlighted for POSIX shell, which leaves a lot of syntax that's valid in bash highlighted in red. To get bash highlighting:
" Set a variable on the buffer that tells the sh syntax highlighter
" that this is bash:
let b:is_bash = 1
" Set the filetype to sh
set ft=sh
Note that if your ft is already sh, you still need the set command; otherwise the let doesn't take effect immediately.
You can make this a global default by making the variable global, i.e., let g:is_bash = 1.
:help ft-sh-syntax is the manual page I had to find; it explains this, and how to trigger highlighting of other flavors of shell.
Vim can also detect file types by inspecting their contents (like for example if the first line contains a bash shebang), here is a quote from filetype.txt help file:
If your filetype can only be detected by inspecting the contents of the file
Create your user runtime directory. You would normally use the first item of the 'runtimepath' option. Example for Unix:
:!mkdir ~/.vim
Create a vim script file for doing this. Example:
if did_filetype() " filetype already set..
finish " ..don't do these checks
endif
if getline(1) =~ '^#!.*\<mine\>'
setfiletype mine
elseif getline(1) =~? '\<drawing\>'
setfiletype drawing
endif
See $VIMRUNTIME/scripts.vim for more examples.
Write this file as "scripts.vim" in your user runtime directory. For
example, for Unix:
:w ~/.vim/scripts.vim
The detection will work right away, no need to restart Vim.
Your scripts.vim is loaded before the default checks for file types, which
means that your rules override the default rules in
$VIMRUNTIME/scripts.vim.
Vim can detect the file type reading the first line. Add the following line as first line.
#!/bin/sh
For those who have a variant of this question i.e. how to enable syntax highlighting on bash files without .sh extension automatically when opened...
Add filetype on in your .vimrc. This enables file type detection by also considering the file's contents. For example, bash scripts will be set to sh file-type. However, typing the #! won't trigger file type detection on a new file created with vim and you will need to use set ft=sh in that case. For more info, type :h filetype in vim.
As mentioned in the comments, you will need to use this in conjuction with syntax enable to turn on highlighting.
Or you could use :filetype detect.
From the doc:
Use this if you started with an empty file and typed text that makes
it possible to detect the file type. For example, when you entered
this in a shell script: "#!/bin/csh".
Once you add the shebang at the top of the file, save it and reload it (e.g. :w|e) and syntax coloring can kick in.
See also Vim inconsistently syntax highlighting bash files, the accepted answer may help as well.
vim already recognizes many file types by default. Most of them work by file extensions, but in a case like this, vim will also analyze the content of the file to guess the correct type.
vim sets the filetype for specific file names like .bashrc, .tcshrc, etc. automatically. But a file with a .sh extension will be recognized as either csh, ksh or bash script. To determine what kind of script this is exactly, vim reads the first line of the file to look at the #! line.
If the first line contains the word bash, the file is identified as a bash script. Usually you see #!/bin/bash if the script is meant to be executed directly, but for a shell configuration file using a simple # bash would work as well.
If you want to look at the details, this is implemented in $VIMRUNTIME/filetype.vim.
Probably the easiest way to get syntax highlighting on a new file, is to just reload it after writing the shebang line. A simple :w :e will write out the file, reload it, and interprete the shebang line you have just written to provide you with the appropriate syntax highlighting.
If you already know the file-type before opening the script or if you're creating a new script without an extension which is common, you can pass it to vim on the command-line like so:
vim -c 'setfiletype sh' path/to/script
vim -c 'setfiletype python' path/to/script
To toggle syntax highlight on/off while you're inside the editor.
Turn on
:syntax on
Turn off
:syntax off
Run this to always have syntax highlighting on when opening vim.
echo ":syntax on" >> ~/.vimrc
When you create a new file, only the filename detection comes into play; content detection (#!/bin/bash) doesn't apply if you type it after creating a new buffer.
The sensible thing is to just do :set ft=bash the first time around, and the next time you edit it, the #!/bin/bash will set the right filetype automatically.
So I work in a PHP shop, and we all use different editors, and we all have to work on Windows. I use vim, and everyone in the shop keeps complaining that whenever I edit a file there is a newline at the bottom. I've searched around and found that this is a documented behavior of vi & vim... but I was wondering if there was some way to disable this feature. (It would be best if I could disable it for specific file extensions).
If anyone knows about this, that would be great!
And for vim 7.4+ you can use (preferably on your .vimrc) (thanks to 罗泽轩 for that last bit of news!):
:set nofixendofline
Now regarding older versions of vim.
Even if the file was already saved with new lines at the end:
vim -b file
and once in vim:
:set noeol
:wq
done.
alternatively you can open files in vim with :e ++bin file
Yet another alternative:
:set binary
:set noeol
:wq
see more details at Why do I need vim in binary mode for 'noeol' to work?
Add the following command to your .vimrc to turn of the end-of-line option:
autocmd FileType php setlocal noeol binary fileformat=dos
However, PHP itself will ignore that last end-of-line - it shouldn't be an issue. I am almost certain that in your case there is something else which is adding the last newline character, or possibly there is a mixup with windows/unix line ending types (\n or \r\n, etc).
Update:
An alternative solution might be to just add this line to your .vimrc:
set fileformats+=dos
There is another way to approach this if you are using Git for source control. Inspired by an answer here, I wrote my own filter for use in a gitattributes file.
To install this filter, save it as noeol_filter somewhere in your $PATH, make it executable, and run the following commands:
git config --global filter.noeol.clean noeol_filter
git config --global filter.noeol.smudge cat
To start using the filter only for yourself, put the following line in your $GIT_DIR/info/attributes:
*.php filter=noeol
This will make sure you do not commit any newline at eof in a .php file, no matter what Vim does.
And now, the script itself:
#!/usr/bin/python
# a filter that strips newline from last line of its stdin
# if the last line is empty, leave it as-is, to make the operation idempotent
# inspired by: https://stackoverflow.com/questions/1654021/how-can-i-delete-a-newline-if-it-is-the-last-character-in-a-file/1663283#1663283
import sys
if __name__ == '__main__':
try:
pline = sys.stdin.next()
except StopIteration:
# no input, nothing to do
sys.exit(0)
# spit out all but the last line
for line in sys.stdin:
sys.stdout.write(pline)
pline = line
# strip newline from last line before spitting it out
if len(pline) > 2 and pline.endswith("\r\n"):
sys.stdout.write(pline[:-2])
elif len(pline) > 1 and pline.endswith("\n"):
sys.stdout.write(pline[:-1])
else:
sys.stdout.write(pline)
I have not tried this option, but the following information is given in the vim help system (i.e. help eol):
'endofline' 'eol' boolean (default on)
local to buffer
{not in Vi}
When writing a file and this option is off and the 'binary' option
is on, no <EOL> will be written for the last line in the file. This
option is automatically set when starting to edit a new file, unless
the file does not have an <EOL> for the last line in the file, in
which case it is reset.
Normally you don't have to set or
reset this option. When 'binary' is
off the value is not used when writing
the file. When 'binary' is on it is
used to remember the presence of a
for the last line in the file,
so that when you write the file the
situation from the original file can
be kept. But you can change it if you
want to.
You may be interested in the answer to a previous question as well: "Why should files end with a newline".
I've added a tip on the Vim wiki for a similar (though different) problem:
http://vim.wikia.com/wiki/Do_not_auto-add_a_newline_at_EOF
OK, you being on Windows complicates things ;)
As the 'binary' option resets the 'fileformat' option (and writing with 'binary' set always writes with unix line endings), let's take out the big hammer and do it externally!
How about defining an autocommand (:help autocommand) for the BufWritePost event? This autocommand is executed after every time you write a whole buffer. In this autocommand call a small external tool (php, perl or whatever script) that strips off the last newline of the just written file.
So this would look something like this and would go into your .vimrc file:
autocmd! "Remove all autocmds (for current group), see below"
autocmd BufWritePost *.php !your-script <afile>
Be sure to read the whole vim documentation about autocommands if this is your first time dealing with autocommands. There are some caveats, e.g. it's recommended to remove all autocmds in your .vimrc in case your .vimrc might get sourced multiple times.
I've implemented Blixtor's suggestions with Perl and Python post-processing, either running inside Vim (if it is compiled with such language support), or via an external Perl script. It's available as the PreserveNoEOL plugin on vim.org.
Starting with vim v7.4 you can use
:set nofixendofline
There is some information about that change here: http://ftp.vim.org/vim/patches/7.4/7.4.785 .
Maybe you could look at why they are complaining. If a php file has a newline after the ending ?>, php will output it as part of the page. This is not a problem unless you try to send headers after the file is included.
However, the ?> at the end of a php file is optional. No ending ?>, no problem with a newline at the end of the file.
Try to add in .vimrc
set binary
I think I've found a better solution than the accepted answer. The alternative solutions weren't working for me and I didn't want to have to work in binary mode all the time.
Fortunately this seems to get the job done and I haven't encountered any nasty side-effects yet: preserve missing end-of-line at end of text files. I just added the whole thing to my ~/.vimrc.
Would it be possible for you to use a special command for saving these files?
If you do :set binary, :w and :set nobinary the file will be written without newline if there was none to start with.
This sequence of commands could be put into a user defined command or a mapping, of course.
I found this vimscript plugin is helpful for this situation.
Plugin 'vim-scripts/PreserveNoEOL'
Or read more at github