How can I take a form and in order to make it an argument of another function surround it with parentheses with one command?
For the example below, assume the cursor starts at the beginning and I do not move it throughout.
(max 1 2 3)
->
((max 1 2 3))
->
(= 3 (max 1 2 3))
So my commands would be:
'magic-key-combination' -> '=' -> ' ' -> '3'
There is no single built-in command that does all of that, however, you can bind a key to multiple commands.
Try putting the following in your user.keymap file (just replace "ctrl-m" with your preferred magic-key-combination).
{:+ {...
:editor {...
"ctrl-m" [:paredit.select.parent
(:editor.open-pair "(")
:paredit.move.down.backward
:paredit.move.up.backward
:editor.char-right]
...}}}
See I can't find a light table cheat sheet for details of the what each individual paredit command does, and tweak as required!
Here is another option that I use constantly. Starting with "(max 1 2 3)", I would type "= 3 " before the opening paren, resulting in this:
= 3 (max 1 2 3)
Then, I select the entire expression and type an opening paren. LightTable automatically inserts the closing paren at the end of the selection:
(= 3 (max 1 2 3))
You may still decide to use a key binding, but this trick is good to know.
Related
I enter:
=IF(D4=”4x4”, _4x4PT*e4, IF(D4=”4x6”,_4x6PT*e4, 0))
when I press I get:
Err:501
When I click on the cell I see:
=IF(D4=”4x4”, _4x4PT*e4, IF(D4=”4x6”,_4x6PT*e4, 0)))
Libreoffice has added an extra paren(s) at the end?
(_4X4PT and _4x6PT are cell names)
Substituting 7 and 11 for the two cell names makes no difference
How do I fix this?
Don't use smart quotes ”. Calc expects normal quotes " instead. Now Calc will no longer add an extra parenthesis.
Depending on regional settings, you may now get Err:508 and need to change the commas , to semicolons ; instead. Semicolons are universally accepted by Calc as a delimiter.
Entering the following expression does not produce an error:
=IF(D4="4x4"; _4x4PT*e4; IF(D4="4x6";_4x6PT*e4; 0))
When analyzing large log files, I often remove lines containing text I find irrelevant:
:g/whatever/d
Sometimes I find text that spans multiple lines, like stacktraces. For that, I record the steps taken (search, go to start anchor, delete to end anchor) and replay that macro with 100000#q. I'm searching for a function or a feature vim already has included that allows me to mark text and remove all lines containing this text. Ideally this would also work for block selection.
If I understood your problem right, this command should do what you want:
:g/NullPointer/,/omitt/d
Example:
Before:
1
2
3
NullPointerException1
4
5
6
omitted
7
NullPointerException2
8
9
omitted
10
After:
1
2
3
7
10
Please read :h edit-paragraph-join, there is good explanation for the command, your case is just changing join into d
:g/whatever/d2
will delete a line with whatever and the line after it. If you can find text that always happens in the first line, you can strip out all of the following text if it has the same number of lines by changing 2 to whatever you need.
You could actually just use some normal commands in a global command to achieve what you want, look at your example (hope i understood it more or less right):
someText
NullPointerException
...
omitted
you want to delte from the line above NPE until the line with omitted right?
Just use the following:
:g/NullPointerException/execute "normal! kddd/omitted\<cr>dd"
It maybe looks complex, but it isn't. It is not better than a macro1
, but i like commands more, because I always make errors recording macros.
Since it only uses normal vim movements, it is easy to adopt. If you f.e. not know where your previous anchor is, you could use ?anchor\<cr> instead of kd. For a better demonstration you will have to submit a realistic example.
[1] You could argue, that this only needs to be run once, but that is also true for a recursive macro http://vim.wikia.com/wiki/Record_a_recursive_macro
Thanks to the answers here, I was able to code a very handy function: The sources below enables one to select text and remove all lines with the same (or similar) text in the current buffer. That works with both in-line and multiline selection. As I said I was searching for something that made me faster in analyzing log files. Log files typically contain dates and times and these change all the time, so it's a good idea to have something that let's us ignore numbers. Let's see. I'm using these two mappings:
vnoremap d :<C-U>echo RemoveSelectionFromBuffer(0)<CR>
vnoremap D :<C-U>echo RemoveSelectionFromBuffer(1)<CR>
Typical usage:
Remove similar lines ignoring numbers: Shift+v, then Shift+d
Remove same matches (single line): Mark text inline (leaving out dates and times), then d
Remove same matches (multiline): Mark text across lines (leaving out dates and times), then d
Here's the source code:
" Removes lines matching the selected text from buffer.
function! RemoveSelectionFromBuffer(ignoreNumbers)
let lines = GetVisualSelection() " selected lines
" Escape backslashes and slashes (delimiters)
call map(lines, {k, v -> substitute(v, '\\\|/', '\\&', 'g')})
if a:ignoreNumbers == 1
" Substitute all numbers with \s*\d\s* - in formatted output matching
" lines may have whitespace instead of numbers. All backslashes need
" to be escaped because \V (very nomagic) will be used.
call map(lines, {k, v -> substitute(v, '\s*\d\+\s*', '\\s\\*\\d\\+\\s\\*', 'g')})
endif
let blc = line('$') " number of lines in buffer (before deletion)
let vlc = len(lines) " number of selected lines
let pattern = join(lines, '\_.') " support multiline patterns
let cmd = ':g/\V' . pattern . '/d_' . vlc " delete matching lines (d_3)
let pos = getpos('v') " save position
execute "silent " . cmd
call setpos('.', pos) " restore position
let dlc = blc - line('$') " number of deleted lines
let dmc = dlc / vlc " number of deleted matches
let cmd = substitute(cmd, '\(.\{50\}\).*', '\1...', '') " command output
let lout = dlc . ' line' . (dlc == 1 ? '' : 's')
let mout = '(' . dmc . ' match' . (dmc == 1 ? '' : 'es') . ')'
return printf('%s removed: %s', (vlc == 1 ? lout : lout . ' ' . mout), cmd)
endfunction
I took the GetVisualSelection() code from this answer.
function! GetVisualSelection()
if mode() == "v"
let [line_start, column_start] = getpos("v")[1:2]
let [line_end, column_end] = getpos(".")[1:2]
else
let [line_start, column_start] = getpos("'<")[1:2]
let [line_end, column_end] = getpos("'>")[1:2]
end
if (line2byte(line_start)+column_start) > (line2byte(line_end)+column_end)
let [line_start, column_start, line_end, column_end] =
\ [line_end, column_end, line_start, column_start]
end
let lines = getline(line_start, line_end)
if len(lines) == 0
return ''
endif
let lines[-1] = lines[-1][: column_end - 1]
let lines[0] = lines[0][column_start - 1:]
return lines
endfunction
Thanks, aepksbuck, DoktorOSwaldo and Kent.
I have an input file like this
line 1
line 2
line 3
There are four spaces before all the lines I want to replace.
I want the end result to be:
A[line 1
A[line 2
A[line 3
(Its funny, so editor doesn't want to display line by line)
I tried M-x replace-regex ^[]+ -> A\[, but get error invalid regex "Unmatched [ or [^"
I tried M-x replace-regex ^[]+ -> A[, but get same error.
Replacing the [ is a problem. How to fix this?
Try
M-x query-replace-regex RET ^ RET A[ RET
^^^
notice the 4 spaces here
In your examples you are missing a space inside the character class: ^[ ]+
Prettier would probably be: ^[[:space:]]+ for every kind of white-space.
Rectangles give you another way to deal with these issues. Cua-mode provides an even nicer system. To use it, first add the following to your .emacs:
(setq cua-enable-cua-keys nil)
(cua-mode)
Then, with point at the * in the following:
* line 1
line 2
line 3
Hit C-enter, and use the arrow keys (or C-n and C-f) to move point to:
line 1
line 2
*line 3
The blanks will all be highlighted. Type A[ to insert the characters. Then hit C-w to delete the spaces.
M-x query-replace-regex RET ^ + RET A[ RET
as it's a single kind of characters to replace, brackets or class are not needed
In Emacs I would like to write some regexp that does the following:
First, return a list of all dictionary words that can be formed within "hex space". By this I mean:
#000000 - #ffffff
so #00baba would be a word (that can be looked up in the dictionary)
so would #baba00
and #abba00
and #0faded
...where trailing and leading 0's are considered irrelevant. How would I write this? Is my question clear enough?
Second, I would like to generate a list of words that can be made using numbers as letters:
0 = o
1 = i
3 = e
4 = a
...and so on. How would I write this?
First, load your dictionary. I'll assume that you're using /var/share/dict/words, which is nearly always installed by default when you're running Linux. It lists one word per line, which is a very handy format for this sort of thing.
Next run M-x keep-lines. It'll ask you for a regular expression and then delete any line that doesn't match it. Use the regex ^[a-f]\{,6\}$ and it will filter out anything that can't be part of a color.
Specifically, the ^ makes the regex start at the beginning of the line, the [a-f] matches any one character that is between a and f (inclusive), the {,6} lets it match between 0 and 6 instances of the previous item (in this case the character class [a-f] and finally the $ tells it that the next thing must be the end of the line.
This will return a list of all instances of #000000 - #ffffff in the buffer, although this pattern may not be restrictive enough for your purposes.
(let ((my-colour-list nil))
(save-excursion
(goto-char (point-min))
(while (re-search-forward "#[0-9a-fA-F]\\{6\\}" nil t)
(add-to-list 'my-colour-list (match-string-no-properties 0)))
my-colour-list))
I'm not actually certain that this is what you were asking for. What do you mean by "dictionary"?
A form that will return you a hash table with all the elements you specify in it could be this:
(let ((hash-table (make-hash-table :test 'equal)))
(dotimes (i (exp 256 3))
(puthash (concat "#" (format "%06x" i)) t hash-table))
hash-table)
I'm not sure how Emacs will manage that size of elements (16 million). As you don't want the 0, you can generate the space without that format, and removing trailing 0's. I don't know what do you want to do with the rest of the numbers. You can write the function step by step like this then:
(defun find-hex-space ()
(let (return-list)
(dotimes (i (exp 256 3))
(let* ((hex-number (strip-zeros (format "%x" i)))
(found-word (gethash hex-number *dictionary*)))
(if found-word (push found-word return-list))))
return-list))
Function strip-zeros is easy to write, and here I suppose your words are in a hash called *dictionary*. strip-zeros could be something like this:
(defun strip-zeros (string)
(let ((sm (string-match "^0*\\(.*?\\)0*$" string)))
(if sm (match-string 1 string) string)))
I don't quite understand your second question. The words would be also using the hex space? Would you then consider only the words formed by numbers, or would also include the letters in the word?
What would be the most straightforward way to emulate the same numeric matching that is used for the expressions in the first five fields of a crontab line?
For example, given inputs of a pattern "1,5-7,16,*/3" (silly example, I know) and a value "6", the output would be a boolean true.
If there isn't a dead simple solution, it'd be realistic in my situation to provide a third input which would specify the maximum value that an asterisk would need to match, so that asterisks (along with the hyphenated ranges) could be translated to a list of values and the input value could be matched against that list. (The list of the example pattern above would be "1,3,5,6,7,9,12,15,16,18", given a maximum value of "18".)
Thanks!
I'm mostly a ksh person, but my experience with bash says this should work (given your example), or at least point you towards what needs to be done.
hrVal=6
case ${hrVal} in
1|[5-7]|16 ) print -- "true" ;;
* ) print -- "false" ;;
esac
Edit 2018-08-20 For bash, you'll need to change print -- to either echo .... or printf "%s\n".
In reality, I would remove the print -- "" stuff, and just call exit 0 or exit 1, which will then exit with the appropriate return code, that can then be tested by the calling process.
to include the rest of your example, I had to do
hrVal=6
eval "
case ${hrVal} in
1|[5-7]|16|$(( ${hrVal} / 3 )) ) print -- "true" ;;
* ) print -- "false" ;;
esac
"
So, this could be exciting!
Parse each of 5 time bands as above
apply sed like commands to convert he entries like 1,5-7,16 into 1|[5-7]|16
trap and convert your math expressions into evaluatable expressions
(oh, you can probably get the result before the case statement and
just merge the value into the ....) save all derived values as
variables,
use those variables as case targets, possible wrapping the whole thing and escaping chars as needed with an eval.
evaluate the combined truth of all 5 columns return values (any false == false)
(maybe it is (( ${hrVal} / 3 )) in bash )
IHTH