Emacs CSS mode won't indent values across multiple lines - css

When a line in my CSS file appears to be too long (typically a property followed by a bunch of values), I want to split them in to several new lines like this (sorry for my low reputation):
https://i.stack.imgur.com/bxXvv.png
But I have to manually enter spaces before the lines to achieve that. In reality, when I hit TAB with my cursor on the url line, what I get is this:
https://i.stack.imgur.com/r4nxa.png
The worst thing is that, after manually inserting the spaces, when I hit TAB again on the same line, it goes back to the ugly format due to indent-region.
This is not a significant issue but it really pains me and I really hope we can have a decent solution here. Thanks in advance!
M-x version:
GNU Emacs 25.1.1 (x86_64-apple-darwin16.1.0, NS appkit-1504.60 Version 10.12.1 (Build 16B2555)) of 2016-11-27
EDIT:
Also tried web-mode for css files and xah-css-mode. None of them worked out.

css-mode uses smie for indentation. It looks like the : in that scenario is tokenized as ":-property". One option would be changing the css-smie-rules to include another rule for indenting after that token.
Evaluating the following redefinition seems to give the indentation you want,
(defun css-smie-rules (kind token)
(pcase (cons kind token)
(`(:elem . basic) css-indent-offset)
(`(:elem . arg) 0)
(`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
(`(:before . "{")
(when (or (smie-rule-hanging-p) (smie-rule-bolp))
(smie-backward-sexp ";")
(smie-indent-virtual)))
(`(:before . ,(or "{" "("))
(if (smie-rule-hanging-p) (smie-rule-parent 0)))
;; *** Additional rule ***
(`(:after . ":-property") css-indent-offset)))
There is the command smie-config-show-indent that is useful to determine what indentation rules are being used at a given point.

#jenesaisquoi mentioned smie and provided an example which is really helpful. Here's my maybe-final solution to my own question.
Add these to the init.el file:
(require 'smie)
(defun css-smie-rules (kind token)
(pcase (cons kind token)
(`(:elem . basic) css-indent-offset)
(`(:elem . arg) 0)
(`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
(`(:before . "{")
(when (or (smie-rule-hanging-p) (smie-rule-bolp))
(smie-backward-sexp ";")
(smie-indent-virtual)))
(`(:before . ,(or "{" "("))
(if (smie-rule-hanging-p) (smie-rule-parent 0)))
;; *** Additional rules below ***
(`(:after . ":") css-indent-offset)
(`(:after . ",") css-indent-offset)))
The syntax is pretty self-explaining.
Maybe there are some ways to modify a function without re-writing it, but I'm not familiar with all the advice thing yet, so if I find a more elegant way I'll come back and edit.
Go to jenesaiquoi's answer for the best solution we can have now.
I've opened a issue for web-mode in Github, and the author of web-mode is now working on it. We will soon see an integrated support for the indentation I mentioned in the question.

Related

Emacs auto-complete for ESS in tooltip instead of buffer

I understand from the following resources:
http://www.emacswiki.org/emacs/ESSAuto-complete
http://www.emacswiki.org/emacs/AutoComplete
Emacs autocomplete-mode extension for ESS and R
Is it possible to get code completion for R in Emacs ESS similar to what is available in Rstudio?
...that I should have access to tooltips for auto-complete help in emacs when using ESS for R development. The last link additionally specifies that it should work out of the box with the latest ESS, and:
From version 12.03 ESS integrates out of the box with auto-complete
package.
Three sources ‘ac-source-R-args’, ‘ac-source-R-objects’ and
‘ac-source-R’ are included in ESS distribution. The latest combines
previous two and makes them play nicely together.
I know that in general, my emacs tooltips are possible because they appear correctly with my python jedi setup in emacs.
However, my emacs auto-complete does not work. Instead, there is a buffer at the bottom:
instead of this, with the help superimposed on the working buffer:
And I have the following in my init.el:
(require 'auto-complete)
(setq ess-use-auto-complete t)
(ess-toggle-underscore nil)
I have the following versions of:
ess 20131207.1141 installed No description available.
ess-R-data-view 20130509.458 installed Data viewer for GNU R
ess-R-object-popup 20130302.336 installed popup description of R object
auto-complete 20140208.653 installed Auto Completion for GNU Emacs
What am I missing?
UPDATE 1
Here's my init for ESS stuff. This produces completions in a buffer, but not in a tooltip, where some configuration options from the manual have been added. (I have now tried all permutations of commenting and not commenting all of these):
(require 'auto-complete)
(global-auto-complete-mode)
(require 'auto-complete-config)
(ac-config-default)
(require 'ess-site)
(setq ess-use-auto-complete t)
(setq ac-auto-start 2)
(setq ac-auto-show-menu 0.2)
(ess-toggle-underscore nil)
UPDATE 2
Similar question here, but the same solution is suggested which did not actually result in tooltips on my setup. But it suggests to me this might be a platform issue? The poster there was also on Ubuntu 12.04 as I am---is it possible the solutions that worked for VitoshKa, Alex Vorobiev, and Iqbal Ansari were on a different platform? Are you guys using OS X?
UPDATE 3
Maybe other diagnostics:
ac-source-R is a variable defined in `ess-r-d.el'.
Its value is ((prefix . ess-ac-start)
(candidates . ess-ac-candidates)
(document . ess-ac-help))
Documentation:
Combined ad-completion source for R function arguments and R objects
ac-source-R-objects is a variable defined in `ess-r-d.el'.
Its value is ((prefix . ess-symbol-start)
(candidates . ess-ac-objects)
(document . ess-ac-help-object))
Documentation:
Auto-completion source for R objects
ac-source-R-args is a variable defined in `ess-r-d.el'.
Its value is ((prefix . ess-ac-start-args)
(candidates . ess-ac-args)
(document . ess-ac-help-arg))
Documentation:
Auto-completion source for R function arguments
[back]
where the variables for ess-ac[TAB] are only...
Click <mouse-2> on a completion to select it.
In this buffer, type RET to select the completion near point.
Possible completions are:
ess-ac-R-argument-suffix
ess-ac-sources
So maybe the problem is my ESS install is lacking all ess-ac-* things defined above, like ess-ac-args, etc?
My auto-complete configuration also has
(require 'auto-complete-config)
(ac-config-default)
and after that setting ess-use-auto-complete makes ESS show the popup menus.
So as per your comments it turned out that auto-complete was not enabled in your emacs config. So just enable auto-complete by adding something like this in you init file
(load "auto-complete")
(global-auto-complete-mode)
Also for ESS you will need to set ess-use-auto-complete to t something like following would do
(setq ess-use-auto-complete t)
EDIT: ess-use-auto-complete is by default set to t so this step is not really needed.
Also since you found this option confusing I would recommend you to open an issue on the github repo so that the maintainers can improve the documentation (or code) whichever can reduce the confusion.
Auto-complete has a lot of configuration options do read the manual when you get time.
Glad I could help
Don't confuse eldoc with auto-completion. Eldoc is what you have in your screenshot, it shows all arguments of a function without being intrusive. Auto-completion pops up when you start typing stuff and activates after ac-auto-start characters.

ECB: tag file prompts?

I've been working on ECB for a small time - and suddenly ECB started to ask me which tags file to open. I've no idea what it talks about - my source codes are usually small... So I think I can be happy without those tag files. How can I turn of this tag-file prompts?
The following solves the problem:
(setq tags-file-name (expand-file-name "~/its/dbes/etgs/TAGS"))
So the emacs doesn't ask about the tag file anymore.
It might be useful to tag only given set of files (for example libs). For that - remove ~/.emacs.d/semanticdb dir, and turn off
(setq global-semanticdb-minor-mode nil)
then one should open the libs one would like to tag, and call
(semantic-force-refresh)
(default key C-c , ,)

user-input and ESS

When you ask ESS to evaluate the following from a buffer (C-c, C-b, or similar)
par(ask=TRUE)
plot(1,1)
plot(2,1)
The interpreter goes into a infinite loop because ESS starts the R session with the argument --no-readline. The loop can be broken with C-g, but is there any way to get the interpreter to actually request user input?
A solution is to edit ess-r-d.el and remove the hard-coded --no-runtime option given to R, it is line 127 of the latest implementation.
Change
(let* ((r-always-arg
(if (or ess-microsoft-p (eq system-type 'cygwin))
"--ess "
"--no-readline "))
to
(let* ((r-always-arg
(if (or ess-microsoft-p (eq system-type 'cygwin))
"--ess "))
If there is a compiled version, you have to compile the .el to generate and replace the binary .elc file.
The file may be (the location of the directory depends on your OS)
in the site-lisp directory. Edit the .el file in emacs (^X^F) then do M-x byte-compile-file to generate the .elc.
if you installed from the whole zip/tar source package, in the lisp directory. In this case, after the change, perform a make followed with a make install.
You need of course to have write access to the .el and .elc files.
If you do not feel comfortable with the compilation of the .el file, you may simply remove it (.elc) and use only the .el version (should be only a slight performance difference).
(Strategies gathered from Google and RSiteSearches):
Do you see the prompt : "hit Return" in any of your session windows? If so ... hit .
If not, then try clicking in the plot window.
And if that fails, you should get control back with c-G.
Edit: A further strategy, admittedly not solving the ESS-non-interactivity problem: If you want to hold for user input, then readLines can be used:
input=file("stdin")
print(readLines(input,1))

Is it possible to have a multi-line comments in R? [duplicate]

This question already has answers here:
Multiline Comment Workarounds?
(11 answers)
Closed 9 years ago.
I found this old thread (from over a year ago), which explains how come R doesn't support a multi-line comments (like /* comment */ of PHP, for example).
I am wondering if this has been resolved in the past year, or if there are other alternatives? (For example, in notepad++ with npptor, you can mark a bunch of lines and press ctrl+q to mark them all as comments, are there similar solutions for other IDE's ?)
R Studio (and Eclipse + StatET): Highlight the text and use CTRL+SHIFT+C to comment multiple lines in Windows.
For macOS, use command+SHIFT+C.
You can, if you want, use standalone strings for multi-line comments — I've always thought that prettier than if (FALSE) { } blocks. The string will get evaluated and then discarded, so as long as it's not the last line in a function nothing will happen.
"This function takes a value x, and does things and returns things that
take several lines to explain"
doEverythingOften <- function(x) {
# Non! Comment it out! We'll just do it once for now.
"if (x %in% 1:9) {
doTenEverythings()
}"
doEverythingOnce()
...
return(list(
everythingDone = TRUE,
howOftenDone = 1
))
}
The main limitation is that when you're commenting stuff out, you've got to watch your quotation marks: if you've got one kind inside, you'll have to use the other kind for the comment; and if you've got something like "strings with 'postrophes" inside that block, then there's no way this method is a good idea. But then there's still the if (FALSE) block.
The other limitation, one that both methods have, is that you can only use such blocks in places where an expression would be syntactically valid - no commenting out parts of lists, say.
Regarding what do in which IDE: I'm a Vim user, and I find
NERD Commenter an utterly excellent tool for quickly commenting or uncommenting multiple lines. Very user-friendly, very well-documented.
Lastly, at the R prompt (at least under Linux), there's the lovely Alt-Shift-# to comment the current line. Very nice to put a line 'on hold', if you're working on a one-liner and then realise you need a prep step first.
CTRL+SHIFT+C in Eclipse + StatET and Rstudio.
if(FALSE) {
...
}
precludes multiple lines from being executed. However, these lines still have to be syntactically correct, i.e., can't be comments in the proper sense. Still helpful for some cases though.
No multi-line comments in R as of version 2.12 and unlikely to change. In most environments, you can comment blocks by highlighting and toggle-comment. In emacs, this is 'M-x ;'.
Put the following into your ~/.Rprofile file:
exclude <- function(blah) {
"excluded block"
}
Now, you can exclude blocks like follows:
stuffiwant
exclude({
stuffidontwant
morestuffidontwant
})
Unfortunately, there is still no multi-line commenting in R.
If your text editor supports column-mode, then use it to add a bunch of #s at once. If you use UltraEdit, Alt+c will put you in column mode.

What are the dark corners of Vim your mom never told you about? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
There are a plethora of questions where people talk about common tricks, notably "Vim+ctags tips and tricks".
However, I don't refer to commonly used shortcuts that someone new to Vim would find cool. I am talking about a seasoned Unix user (be they a developer, administrator, both, etc.), who thinks they know something 99% of us never heard or dreamed about. Something that not only makes their work easier, but also is COOL and hackish. After all, Vim resides in the most dark-corner-rich OS in the world, thus it should have intricacies that only a few privileged know about and want to share with us.
Might not be one that 99% of Vim users don't know about, but it's something I use daily and that any Linux+Vim poweruser must know.
Basic command, yet extremely useful.
:w !sudo tee %
I often forget to sudo before editing a file I don't have write permissions on. When I come to save that file and get a permission error, I just issue that vim command in order to save the file without the need to save it to a temp file and then copy it back again.
You obviously have to be on a system with sudo installed and have sudo rights.
Something I just discovered recently that I thought was very cool:
:earlier 15m
Reverts the document back to how it was 15 minutes ago. Can take various arguments for the amount of time you want to roll back, and is dependent on undolevels. Can be reversed with the opposite command :later
:! [command] executes an external command while you're in Vim.
But add a dot after the colon, :.! [command], and it'll dump the output of the command into your current window. That's : . !
For example:
:.! ls
I use this a lot for things like adding the current date into a document I'm typing:
:.! date
Not exactly obscure, but there are several "delete in" commands which are extremely useful, like..
diw to delete the current word
di( to delete within the current parens
di" to delete the text between the quotes
Others can be found on :help text-objects
de Delete everything till the end of the word by pressing . at your heart's desire.
ci(xyz[Esc] -- This is a weird one. Here, the 'i' does not mean insert mode. Instead it means inside the parenthesis. So this sequence cuts the text inside parenthesis you're standing in and replaces it with "xyz". It also works inside square and figure brackets -- just do ci[ or ci{ correspondingly. Naturally, you can do di (if you just want to delete all text without typing anything. You can also do a instead of i if you want to delete the parentheses as well and not just text inside them.
ci" - cuts the text in current quotes
ciw - cuts the current word. This works just like the previous one except that ( is replaced with w.
C - cut the rest of the line and switch to insert mode.
ZZ -- save and close current file (WAY faster than Ctrl-F4 to close the current tab!)
ddp - move current line one row down
xp -- move current character one position to the right
U - uppercase, so viwU upercases the word
~ - switches case, so viw~ will reverse casing of entire word
Ctrl+u / Ctrl+d scroll the page half-a-screen up or down. This seems to be more useful than the usual full-screen paging as it makes it easier to see how the two screens relate. For those who still want to scroll entire screen at a time there's Ctrl+f for Forward and Ctrl+b for Backward. Ctrl+Y and Ctrl+E scroll down or up one line at a time.
Crazy but very useful command is zz -- it scrolls the screen to make this line appear in the middle. This is excellent for putting the piece of code you're working on in the center of your attention. Sibling commands -- zt and zb -- make this line the top or the bottom one on the sreen which is not quite as useful.
% finds and jumps to the matching parenthesis.
de -- delete from cursor to the end of the word (you can also do dE to delete until the next space)
bde -- delete the current word, from left to right delimiter
df[space] -- delete up until and including the next space
dt. -- delete until next dot
dd -- delete this entire line
ye (or yE) -- yanks text from here to the end of the word
ce - cuts through the end of the word
bye -- copies current word (makes me wonder what "hi" does!)
yy -- copies the current line
cc -- cuts the current line, you can also do S instead. There's also lower cap s which cuts current character and switches to insert mode.
viwy or viwc. Yank or change current word. Hit w multiple times to keep selecting each subsequent word, use b to move backwards
vi{ - select all text in figure brackets. va{ - select all text including {}s
vi(p - highlight everything inside the ()s and replace with the pasted text
b and e move the cursor word-by-word, similarly to how Ctrl+Arrows normally do. The definition of word is a little different though, as several consecutive delmiters are treated as one word. If you start at the middle of a word, pressing b will always get you to the beginning of the current word, and each consecutive b will jump to the beginning of the next word. Similarly, and easy to remember, e gets the cursor to the end of the current, and each subsequent, word.
similar to b/e, capital B and E move the cursor word-by-word using only whitespaces as delimiters.
capital D (take a deep breath) Deletes the rest of the line to the right of the cursor, same as Shift+End/Del in normal editors (notice 2 keypresses -- Shift+D -- instead of 3)
One that I rarely find in most Vim tutorials, but it's INCREDIBLY useful (at least to me), is the
g; and g,
to move (forward, backward) through the changelist.
Let me show how I use it. Sometimes I need to copy and paste a piece of code or string, say a hex color code in a CSS file, so I search, jump (not caring where the match is), copy it and then jump back (g;) to where I was editing the code to finally paste it. No need to create marks. Simpler.
Just my 2cents.
:%!xxd
Make vim into a hex editor.
:%!xxd -r
Revert.
Warning: If you don't edit with binary (-b), you might damage the file. – Josh Lee in the comments.
gv
Reselects last visual selection.
Sometimes a setting in your .vimrc will get overridden by a plugin or autocommand. To debug this a useful trick is to use the :verbose command in conjunction with :set. For example, to figure out where cindent got set/unset:
:verbose set cindent?
This will output something like:
cindent
Last set from /usr/share/vim/vim71/indent/c.vim
This also works with maps and highlights. (Thanks joeytwiddle for pointing this out.) For example:
:verbose nmap U
n U <C-R>
Last set from ~/.vimrc
:verbose highlight Normal
Normal xxx guifg=#dddddd guibg=#111111 font=Inconsolata Medium 14
Last set from ~/src/vim-holodark/colors/holodark.vim
:%TOhtml
Creates an html rendering of the current file.
Not sure if this counts as dark-corner-ish at all, but I've only just learnt it...
:g/match/y A
will yank (copy) all lines containing "match" into the "a/#a register. (The capitalization as A makes vim append yankings instead of replacing the previous register contents.) I used it a lot recently when making Internet Explorer stylesheets.
Want to look at your :command history?
q:
Then browse, edit and finally to execute the command.
Ever make similar changes to two files and switch back and forth between them? (Say, source and header files?)
:set hidden
:map <TAB> :e#<CR>
Then tab back and forth between those files.
Vim will open a URL, for example
vim http://stackoverflow.com/
Nice when you need to pull up the source of a page for reference.
Macros can call other macros, and can also call itself.
eg:
qq0dwj#qq#q
...will delete the first word from every line until the end of the file.
This is quite a simple example but it demonstrates a very powerful feature of vim
Assuming you have Perl and/or Ruby support compiled in, :rubydo and :perldo will run a Ruby or Perl one-liner on every line in a range (defaults to entire buffer), with $_ bound to the text of the current line (minus the newline). Manipulating $_ will change the text of that line.
You can use this to do certain things that are easy to do in a scripting language but not so obvious using Vim builtins. For example to reverse the order of the words in a line:
:perldo $_ = join ' ', reverse split
To insert a random string of 8 characters (A-Z) at the end of every line:
:rubydo $_ += ' ' + (1..8).collect{('A'..'Z').to_a[rand 26]}.join
You are limited to acting on one line at a time and you can't add newlines.
^O and ^I
Go to older/newer position.
When you are moving through the file (by searching, moving commands etc.) vim rember these "jumps", so you can repeat these jumps backward (^O - O for old) and forward (^I - just next to I on keyboard). I find it very useful when writing code and performing a lot of searches.
gi
Go to position where Insert mode was stopped last.
I find myself often editing and then searching for something. To return to editing place press gi.
gf
put cursor on file name (e.g. include header file), press gf and the file is opened
gF
similar to gf but recognizes format "[file name]:[line number]". Pressing gF will open [file name] and set cursor to [line number].
^P and ^N
Auto complete text while editing (^P - previous match and ^N next match)
^X^L
While editing completes to the same line (useful for programming).
You write code and then you recall that you have the same code somewhere in file. Just press ^X^L and the full line completed
^X^F
Complete file names.
You write "/etc/pass" Hmm. You forgot the file name. Just press ^X^F and the filename is completed
^Z or :sh
Move temporary to the shell. If you need a quick bashing:
press ^Z (to put vi in background) to return to original shell and press fg to return to vim back
press :sh to go to sub shell and press ^D/exit to return to vi back
Typing == will correct the indentation of the current line based on the line above.
Actually, you can do one = sign followed by any movement command. ={movement}
For example, you can use the % movement which moves between matching braces. Position the cursor on the { in the following code:
if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}
And press =% to instantly get this:
if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}
Alternately, you could do =a{ within the code block, rather than positioning yourself right on the { character.
" insert range ip's
"
" ( O O )
" =======oOO=(_)==OOo======
:for i in range(1,255) | .put='10.0.0.'.i | endfor
This is a nice trick to reopen the current file with a different encoding:
:e ++enc=cp1250 %:p
Useful when you have to work with legacy encodings. The supported encodings are listed in a table under encoding-values (see help encoding-values). Similar thing also works for ++ff, so that you can reopen file with Windows/Unix line ends if you get it wrong for the first time (see help ff).
imap jj <esc>
Let's see some pretty little IDE editor do column transposition.
:%s/\(.*\)^I\(.*\)/\2^I\1/
Explanation
\( and \) is how to remember stuff in regex-land. And \1, \2 etc is how to retrieve the remembered stuff.
>>> \(.*\)^I\(.*\)
Remember everything followed by ^I (tab) followed by everything.
>>> \2^I\1
Replace the above stuff with "2nd stuff you remembered" followed by "1st stuff you remembered" - essentially doing a transpose.
Not exactly a dark secret, but I like to put the following mapping into my .vimrc file, so I can hit "-" (minus) anytime to open the file explorer to show files adjacent to the one I just edit. In the file explorer, I can hit another "-" to move up one directory, providing seamless browsing of a complex directory structures (like the ones used by the MVC frameworks nowadays):
map - :Explore<cr>
These may be also useful for somebody. I like to scroll the screen and advance the cursor at the same time:
map <c-j> j<c-e>
map <c-k> k<c-y>
Tab navigation - I love tabs and I need to move easily between them:
map <c-l> :tabnext<enter>
map <c-h> :tabprevious<enter>
Only on Mac OS X: Safari-like tab navigation:
map <S-D-Right> :tabnext<cr>
map <S-D-Left> :tabprevious<cr>
Often, I like changing current directories while editing - so I have to specify paths less.
cd %:h
I like to use 'sudo bash', and my sysadmin hates this. He locked down 'sudo' so it could only be used with a handful of commands (ls, chmod, chown, vi, etc), but I was able to use vim to get a root shell anyway:
bash$ sudo vi +'silent !bash' +q
Password: ******
root#
I often use many windows when I work on a project and sometimes I need to resize them. Here's what I use:
map + <C-W>+
map - <C-W>-
These mappings allow to increase and decrease the size of the current window. It's quite simple but it's fast.
:r! <command>
pastes the output of an external command into the buffer.
Do some math and get the result directly in the text:
:r! echo $((3 + 5 + 8))
Get the list of files to compile when writing a Makefile:
:r! ls *.c
Don't look up that fact you read on wikipedia, have it directly pasted into the document you are writing:
:r! lynx -dump http://en.wikipedia.org/wiki/Whatever
Not an obscure feature, but very useful and time saving.
If you want to save a session of your open buffers, tabs, markers and other settings, you can issue the following:
mksession session.vim
You can open your session using:
vim -S session.vim
Map F5 to quickly ROT13 your buffer:
map <F5> ggg?G``
You can use it as a boss key :).
I use vim for just about any text editing I do, so I often times use copy and paste. The problem is that vim by default will often times distort imported text via paste. The way to stop this is to use
:set paste
before pasting in your data. This will keep it from messing up.
Note that you will have to issue :set nopaste to recover auto-indentation. Alternative ways of pasting pre-formatted text are the clipboard registers (* and +), and :r!cat (you will have to end the pasted fragment with ^D).
It is also sometimes helpful to turn on a high contrast color scheme. This can be done with
:color blue
I've noticed that it does not work on all the versions of vim I use but it does on most.
I just found this one today via NSFAQ:
Comment blocks of code.
Enter Blockwise Visual mode by hitting CTRL-V.
Mark the block you wish to comment.
Hit I (capital I) and enter your comment string at the beginning of the line. (// for C++)
Hit ESC and all lines selected will have // prepended to the front of the line.

Resources