sjl / learnvimscriptthehardway Goto Github PK
View Code? Open in Web Editor NEWHome Page: http://learnvimscriptthehardway.stevelosh.com/
License: Other
Home Page: http://learnvimscriptthehardway.stevelosh.com/
License: Other
The FileType events wont work unless you enable filetype detection, 'filetype on' in the vimrc will do the trick.
First of all, brilliant book. I absolutely love it. The Vim reference manual I needed :)
Secondly, I wonder how you feel about making the book available as a Docset within Dash? I'd be happy to do it myself if needed. It could save me and others a bit of time.
Some info about creating Dash docsets: https://kapeli.com/docsets
Chapter 2 uses numberwidth
as an example of an option that can take a value, and then has the following:
Try checking what a few other common options are set to:
:set wrap?
:set numberwidth?
(emphasis mine)
Chapter 19:
Why would we want to do this when we could just use
set
? Run the following
commands:
:let &textwidth = &textwidth + 10
:set textwidth?
This time Vim displays "textwidth=110". When you set an option using
set
you
can only set it to a single literal value.
But in this case we can also do exactly the same thing with set:
:set textwidth=100
:set textwidth+=10
:set textwidth?
Vim displays "textwidth=110".
In Chapter 15 Operator-Pending Mappings there is an example mapping given for deleting a text inside next parenthesis:
:onoremap
in( :normal! f(vi(`
and in the next paragraph it is explained that
First, the
<c-u>
is something special that you can ignore for now -- just trust me that it needs to be there to make the mappings work in all cases
Actually, in this case the <c-u>
does not serve any purpose. The key combination is used to remove everything from the command line, but in this case there will be nothing anyway.
I think the author took suggestion from the example of VIM documentation:
onoremap <silent> F :<C-U>normal! 0f(hviw<CR>
But in this case, the <c-u>
is indeed necessary, as by F gets VIM into the visual mode and ":" will get it into the visual mode command selection (:'<.>'
), so the key combination is used to clear that out.
So it does not need to be there as the author suggests.
The 'Create a "inside next email address" operator-pending mapping' exercise in Chapter 15 requires a technique which isn't introduced until Chapter 16. This seems a bit unfair!
Just like the title, epub format is better, I hope to read on NOOK2. Thanks. This document is my first book to learn vimscript.
Hi Steve,
I was reading chapter 46 and writing the potion plugin and I think I found an error in the book.
Here you mention that:
Because I used separate regexes for `-` and `-=` I had to define `-` *after*
`-=`!
If I did it in the opposite order and used `-=` in a Potion file, Vim would
match `-` (and highlight it, of course) and only `=` would remain for matching.
This shows when you're building groups with `syntax match` each group "consumes"
pieces of the file that can't be matched later.
This is an oversimplification, but I don't want to get bogged down in the
details just yet. For now, your rule of thumb should be to match larger groups
first and smaller groups later.
However when I gave it a try the *
matched before the *=
. Reading :help syn-priority
it seems that items defined last have higher priority. If I switch things around and define *
before *=
then it works correctly.
Could this have changed from a previous version of vim? Or maybe it went unnoticed because you also had a match for =
? Am I doing something wrong?
Anyway, thanks for the book, I'm enjoying it.
Chapter 32 includes in its exercises:
Read
:help :grep
.
But we were already instructed to read :help :grep
at the start of the chapter.
Near the top of the "Changing the Start" section you introduce the command as:
:onoremap in( :<c-u>normal! f(vi(<cr>
But later on, all references to the movement portion are:
F)vi(
Ch3: When mapleader is unset (which it is by default), '' is the leader, which confuses things a little.
The mappings still work, but there is a pause before they are invoked, while Vim waits to see if you are typing a leader-mapping or not.
website is down, that's all :)
Should it be "write and source the file" like those in other chapters?
I was planning to send a PR for missing extra <cr>
in chapter 32, but found so many opened PRs and last commit is 3 years ago...
The exercise in chapter 49 has an impossible exercise.
We defined our helper functions as global functions, but that's not a good idea. >
Change them to be script-local functions.
Upon attempting this exercise I tried to do:
setlocal foldexpr=<SID>GetPotionFold(v:lnum)
Which, as I know now, is not possible as you cannot use <SID>
in a mapping.
I realise now that I probably misinterpreted the exercise, but if one person can why not another?
It's suggested in the 44.2 exercise that we replace "set filetype" with "setfiletype", but this caused the syntax/potion.vim not to be loaded by default for me. It worked after I changed it back to "set filetype" though.
Vim version: 7.3
It would be great to have not only 'Prev', 'Next' but a 'Table of contents' link at each rendered page. It will simplify navigation significantly. Thanks
When using echom in vimrc to display messages (for example trying to record debugging information in if clauses), they trigger the 'press-enter to continue' dialog.
If you prefix echom with silent, you they won't trigger the 'press-enter to continue' dialog, but they also aren't stored in the message-history buffer.
I've been looking around for awhile, but haven't found any working solutions to this problem (logging debugging messages to message-history with echom, without triggering the press-enter dialog).
I was hoping it would be covered in your manual (which is fantastic, btw), but I don't see it. Do you have any suggestions?
On chapter 34, you teach the how to not pollute the registers and recover the "@
register.
This is correct, but it doesn't work if clipboard
is set to unnamed
. In that case "+
and "*
registers are used instead, so they should also be recovered.
Thanks a lot by the way, I learn a lot from the online version and will definitely buy it as soon as I finish reading it.
If you start accepting PRs again let me know and I'll happily create one.
Isn't execute "normal!
<v>y"
the same as normal!
<v>y
here?
so it's no need to use execute. Comparing to the following sections of the page, execute
is not used in the same code but why it's disappeared is not mentioned. Did you forget to mention about removing execute
or it was just a typo to include it?
Correct me if I am wrong, I am just learning vimscript using your book, but I've mentioned that sometimes very minor inconsistencies in code snippets appear. Eagerly willing to assist in improving the document.
In the Exercises portion of chapter 25:
Read :help Float
. When might floating point number not work in Vimscript?
Should say:
Read :help Float
. When might floating point numbers not work in Vimscript?
\
doesn't do anything.
This isn't true. By default (when mapleader
is unset), \
is the leader!
:normal! ?^==\+$<cr>:nohlsearch<cr>kvg_
Topic One
=========
This is some text about topic one.
It has multiple paragraphs.
Topic Two
=========
This is some text about topic two. It has only one paragraph.
and when I type this command in my vim there have nothing happened
And my vim version is: 8.2.2029
In chapter 35, the reader is asked to run this command:
:echo join(foo)
:echo join(foo, '---')
:echo join([1, 2, 3], '')
The book goes on to say that:
Vim displays "a b" and "a---b". join will join the items in the given list together into a string, separated by the given separator string (or a space if none is given), coercing each item to a string if necessary/possible.
but does not mention "123" (the output of the third command).
As far as I can tell, chapters 29 and 30 are unnecessary (except for a spot of revision) as we've already covered all the material in detail in chapter 16.
Even if you do want to keep the chapters for the sake of reinforcing the lessons within, it's confusing they make no mention of the fact that we've already covered the material a few chapters ago.
In chapter 11, we carry out nnoremap <buffer <leader>x dd
to map <leader>x
locally within the current buffer. We then switch to the other buffer and try pressing the leader followed by the x
key. You then assert that:
Nothing happened!
But that's incorrect. Because there is no mapping defined in this buffer, Vim ignores the leader, and defaults to the normal behaviour of x
, and deletes a character.
Possibly a key sequence which doesn't actually do anything by default should be used for the mapping? Or the text should be changed.
The « Previous » and « Next » links to navigate between pages are broken, and point to the same page.
Step to reproduce :
Expected :
What happens :
Maybe this is a bookmarkdown problem, but I couldn't find another book released with that tool to confirm this assumption.
Chapter 27 says:
"It's up to you to decide whether to use tolower
and ==#
, or just ==?
to perform case-sensitive comparisons."
"case-sensitive" should read "case-insensitive".
In chapter 10, remapping the key in insert mode to 'jk' key combination is proposed.
I Don't know about other languages, but in my native tongue (dutch) the character combination 'jk' is found in a lot of words, using them as a mapping would render vim rather useless for typing my native language:
Example try typing "The rich local police officer irons mud." -> "De rijke wijkagent strijkt slijk" ;-)
Also, since going from insert mode to normal mode generally implies a context switch, I'm not even convinced, other than 'jk' is faster and easier typed than hitting , the remap increases overall editing efficiency.
But this is probably a whole new discussion altogether, maybe a small note re. the 'jk' map and other languages than English would be warranted?
In Chapter 5, we add the mapping :nmap dd O<esc>jddk
, which creates an infinite recursion.
Then, slightly further down, we do:
:nmap x dd
:nnoremap \ x
If the reader decides to try out their x
mapping before trying the \
mapping, then they will hit the infinite recursion that we mapped dd
to above. I don't think this is what was intended.
On the other hand, as Chapter 5 is all about avoiding unintended consequences from mappings invoking other mappings, maybe this might actually be a good thing to leave in!
The error in Color Schemes.
阅读:help highlgiht来学习基础知识。
(The error in here, Not is highlgiht. The error is only in Chinese version.)
(Since this issue will likely not be addressed in the book itself due to #95, may it hopefully be informative to whomever happens to come across it...)
Chapter 32, section "Escaping Shell Command Arguments", ends with
Now that we know how to get a fully-escaped version of the word under the cursor, it's time to concatenate it into our mapping! Run the following command:
:nnoremap <leader>g :exe "grep -R " . shellescape(expand("<cWORD>")) . " ."<cr>
Try it out. This mapping won't break if the word we're searching for happens to contain strange characters.
However, the above mapping breaks if there are special characters in the current WORD
under the cursor. A couple examples of such WORD
s are:
%-percent-char
, which ends up invoking :grep -R '%-percent-char'
and %
expands to the current file name, and<afile>-string
, which errors out with E497: no autocommand match name to substitute for "<afile>"
.A simple fix for this is to pass a non-zero {special}
arg to shellescape({string} [, {special}])
, which will escape special items as well. With this knowledge, the final mapping can be further refined as follows:
:nnoremap <leader>g :exe "grep -R " . shellescape(expand("<cWORD>"), 1) . " ."<cr>
The final line of the function echoes the variable @@. Remember that variables starting with an @ are registers. @@ is the "unnamed" register: the one that Vim places text into when you yank or delete without specify a particular register.
Pretty sure this isn't correct. The unnamed register is @". Not sure what you call @@ but it's like the "repeat last register" register.
I think it could be very helpful if learnvimscriptthehardway had a bit about how to map functions to commands somewhere around the "Functions" section or "Function Arguments" section.
Specifically if there was an example where someone was walked through the process of defining a function in their vimrc and then mapped it to a command.
learnvimscriptthehardway is my favorite resource for finding out how to do things in vim, and I had to do some googling and reading :help command
to figure out how to do this
Hi there,
Thanks for the great work!
I noticed a broken link in the footer. The one to BookMarkDown that points to an unavailable repository: https://bitbucket.org/sjl/bookmarkdown/
I think it should now point to: https://github.com/JerrySievert/bookmarkdown
Cordially,
RilDev
Because I am stupid, I keep getting stuck and tweeting you to find the answers for the exercises. Perhaps including links to answers might be a good idea?
In all your discussion of how local options work (e.g. Chapter 11, Chapter 19) you instruct the reader to first open two windows, and then use :setlocal
or :let &l:
to set various options differently in the two windows. Then you note that the two windows now display differently.
However, this implies that had the reader used the regular set
or let
commands the outcome would have been different, which is not the case.
The problem is that the windows always use their own local values for the option, and this value is copied over from the global value (or when creating a split, from the current window value) when the window is created. Using an unadorned set
will change both the local value for the current window/buffer and the global value, but it will not change the local values for other windows. So the difference between the two commands will only become apparent:
:setglobal ...?
command is used to specifically query the global value.N.B. This (and more--e.g. the difference between "local to buffer" and "local to window" options) is all detailed in :h local-options
. It might be helpful to add reading this as one of the exercises in chapter 11.
Using a bare
nmap
is just asking for pain down the road
So is using a bare vmap! I think the following might be preferable:
Using a bare
*map
is just asking for pain down the road
Also:
Each of the
*map
commands has a*noremap
counterpart that ignores other mappings:nnoremap
,vnoremap
, andinoremap
.
should be:
Each of the
*map
commands has a*noremap
counterpart that ignores other mappings:noremap
,nnoremap
,vnoremap
, andinoremap
.
The section recommends mapping to so we get used to jk
as an easy way to get to normal mode.
On a MacVim 7.4 on OSX Yosemite, arrow keys are implemented as OA, or something. Anyway, this causes the arrow keys to insert random characters instead of their normal function.
(Of course we should be using hjkl anyway ;)
In Chapter 31, there is a link to "Learn Regex The Hard Way" that leads to site that just says "Not Found."
In my copy of Vim, :help number
opens the help for :number
and not 'number'
, which I think is what was intended.
Hiya, love the book.
This might just be my stupidity typing, but I can't seem to replicate inserting two d
s (lol) when I run :imap <c-d> dd
. Nothing really happens when I enter insert mode and press ctrl - d
. Also, running :unmap <c-d>
returns an error E31: No such mapping
.
However, the second map (:imap <c-d> <esc>dd
) it works as intended.
I was attempting to do the exercise in chapter 54:
Suppose you wanted to programatically force a reload of an autoload file Vim has already loaded, without bothering the user. How might you do this? You may want to read :help silent!. Please don't ever do this in real life.
But my vim spits back: E149: Sorry, no help for silent!
I am using vim version 7.3.947 in ase it is relevant.
I do not know what part of the documentation I am intended to read now. :(
I'm not sure if this is a bug, but the changing the start did not work for me at all. I even tried clearing all my mappings, and copy/pasting the example in.
In the last paragraph in the section on Lower and Upper Case the text reads:
It's up to you to decide whether to use
tolower
and==#
, or just==?
to perform case-sensitive comparisons.
It should read:
It's up to you to decide whether to use
tolower
and==#
, or just==?
to perform case-insensitive comparisons.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.