aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/tutor.vim197
-rw-r--r--runtime/ftplugin/tutor.vim19
-rw-r--r--runtime/syntax/tutor.vim22
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor92
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor.json45
-rw-r--r--runtime/tutor/tutor.tutor118
-rw-r--r--runtime/tutor/tutor.tutor.json35
7 files changed, 236 insertions, 292 deletions
diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim
index 43d8a87886..56e2283465 100644
--- a/runtime/autoload/tutor.vim
+++ b/runtime/autoload/tutor.vim
@@ -15,30 +15,17 @@ function! tutor#SetupVim()
endif
endfunction
-" Mappings: {{{1
-
-function! s:CheckMaps()
- nmap
+" Loads metadata file, if available
+function! tutor#LoadMetadata()
+ let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n"))
endfunction
-function! s:MapKeyWithRedirect(key, cmd)
- if maparg(a:key) !=# ''
- redir => l:keys
- silent call s:CheckMaps()
- redir END
- let l:key_list = split(l:keys, '\n')
-
- let l:raw_map = filter(copy(l:key_list), "v:val =~# '\\* ".a:key."'")
- if len(l:raw_map) == 0
- exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd
- return
- endif
- let l:map_data = split(l:raw_map[0], '\s*')
+" Mappings: {{{1
- exe "nnoremap <buffer> <expr> ".l:map_data[0]." ".a:cmd
- else
- exe "nnoremap <buffer> <expr> ".a:key." ".a:cmd
- endif
+function! tutor#SetNormalMappings()
+ nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr>
+ nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr>
+ nnoremap <buffer> >> :call tutor#InjectCommand()<cr>
endfunction
function! tutor#MouseDoubleClick()
@@ -46,7 +33,7 @@ function! tutor#MouseDoubleClick()
normal! zo
else
if match(getline('.'), '^#\{1,} ') > -1
- normal! zc
+ silent normal! zc
else
call tutor#FollowLink(0)
endif
@@ -59,114 +46,6 @@ function! tutor#InjectCommand()
redraw | echohl WarningMsg | echon "tutor: ran" | echohl None | echon " " | echohl Statement | echon l:cmd
endfunction
-function! tutor#SetNormalMappings()
- call s:MapKeyWithRedirect('l', 'tutor#ForwardSkipConceal(v:count1)')
- call s:MapKeyWithRedirect('h', 'tutor#BackwardSkipConceal(v:count1)')
- call s:MapKeyWithRedirect('<right>', 'tutor#ForwardSkipConceal(v:count1)')
- call s:MapKeyWithRedirect('<left>', 'tutor#BackwardSkipConceal(v:count1)')
-
- nnoremap <silent> <buffer> <CR> :call tutor#FollowLink(0)<cr>
- nnoremap <silent> <buffer> <2-LeftMouse> :call tutor#MouseDoubleClick()<cr>
- nnoremap <buffer> >> :call tutor#InjectCommand()<cr>
-endfunction
-
-function! tutor#SetSampleTextMappings()
- noremap <silent> <buffer> A :if match(getline('.'), '^--->') > -1 \| call search('\s{\@=', 'Wc') \| startinsert \| else \| startinsert! \| endif<cr>
- noremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr>
- onoremap <silent> <buffer> $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif<cr>
- noremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr>
- onoremap <silent> <buffer> ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif<cr>
- nmap <silent> <buffer> 0 ^<esc>
- nmap <silent> <buffer> <Home> ^<esc>
- nmap <silent> <buffer> <End> $
- imap <silent> <buffer> <Home> <esc>^<esc>:startinsert<cr>
- imap <silent> <buffer> <End> <esc>$:startinsert<cr>
- noremap <silent> <buffer> I :exe "normal! 0" \| startinsert<cr>
-endfunction
-
-" Navigation: {{{1
-
-" taken from http://stackoverflow.com/a/24224578
-
-function! tutor#ForwardSkipConceal(count)
- let cnt=a:count
- let mvcnt=0
- let c=col('.')
- let l=line('.')
- let lc=col('$')
- let line=getline('.')
- while cnt
- if c>=lc
- let mvcnt+=cnt
- break
- endif
- if stridx(&concealcursor, 'n')==-1
- let isconcealed=0
- else
- let [isconcealed, cchar, group] = synconcealed(l, c)
- endif
- if isconcealed
- let cnt-=strchars(cchar)
- let oldc=c
- let c+=1
- while c < lc
- let [isconcealed2, cchar2, group2] = synconcealed(l, c)
- if !isconcealed2 || cchar2 != cchar
- break
- endif
- let c+= 1
- endwhile
- let mvcnt+=strchars(line[oldc-1:c-2])
- else
- let cnt-=1
- let mvcnt+=1
- let c+=len(matchstr(line[c-1:], '.'))
- endif
- endwhile
- return mvcnt.'l'
-endfunction
-
-function! tutor#BackwardSkipConceal(count)
- let cnt=a:count
- let mvcnt=0
- let c=col('.')
- let l=line('.')
- let lc=0
- let line=getline('.')
- while cnt
- if c<=1
- let mvcnt+=cnt
- break
- endif
- if stridx(&concealcursor, 'n')==-1 || c == 0
- let isconcealed=0
- else
- let [isconcealed, cchar, group]=synconcealed(l, c-1)
- endif
- if isconcealed
- let cnt-=strchars(cchar)
- let oldc=c
- let c-=1
- while c>1
- let [isconcealed2, cchar2, group2] = synconcealed(l, c-1)
- if !isconcealed2 || cchar2 != cchar
- break
- endif
- let c-=1
- endwhile
- let c = max([c, 1])
- let mvcnt+=strchars(line[c-1:oldc-2])
- else
- let cnt-=1
- let mvcnt+=1
- let c-=len(matchstr(line[:c-2], '.$'))
- endif
- endwhile
- return mvcnt.'h'
-endfunction
-
-" Hypertext: {{{1
-
function! tutor#FollowLink(force)
let l:stack_s = join(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), '')
if l:stack_s =~# 'tutorLink'
@@ -209,42 +88,40 @@ function! tutor#InfoText()
return join(l:info_parts, " ")
endfunction
-" Marks {{{1
-function! tutor#PlaceXMarks()
- call cursor(1, 1)
- let b:tutor_sign_id = 1
- while search('^--->', 'W') > 0
- call tutor#CheckText(getline('.'))
- let b:tutor_sign_id+=1
- endwhile
- call cursor(1, 1)
+
+" Marks: {{{1
+
+function! tutor#ApplyMarks()
+ hi! link tutorExpect Special
+ if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
+ let b:tutor_sign_id = 1
+ for expct in keys(b:tutor_metadata['expect'])
+ let lnum = eval(expct)
+ call matchaddpos('tutorExpect', [lnum])
+ call tutor#CheckLine(lnum)
+ endfor
+ endif
endfunction
-function! tutor#CheckText(text)
- if match(a:text, '{expect:ANYTHING}\s*$') == -1
- if match(getline('.'), '^--->\s*$') > -1
- exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%')
- else
- if match(getline('.'), '|expect:.\+|') == -1
- let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze {expect:')
- let l:expected_text = matchstr(a:text, '{expect:\zs.*\ze}\s*$')
- else
- let l:cur_text = matchstr(a:text, '---> \zs.\{-}\ze |expect:')
- let l:expected_text = matchstr(a:text, '|expect:\zs.*\ze|\s*$')
- endif
- if l:cur_text ==# l:expected_text
- exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorok buffer=".bufnr('%')
- else
- exe "sign place ".b:tutor_sign_id." line=".line('.')." name=tutorbad buffer=".bufnr('%')
- endif
+function! tutor#ApplyMarksOnChanged()
+ if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
+ let lnum = line('.')
+ if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1
+ call tutor#CheckLine(lnum)
endif
endif
endfunction
-function! tutor#OnTextChanged()
- let l:text = getline('.')
- if match(l:text, '^--->') > -1
- call tutor#CheckText(l:text)
+function! tutor#CheckLine(line)
+ if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
+ let bufn = bufnr('%')
+ let ctext = getline(a:line)
+ if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)]
+ exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn
+ else
+ exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn
+ endif
+ let b:tutor_sign_id+=1
endif
endfunction
diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim
index 1579753170..ec55472b78 100644
--- a/runtime/ftplugin/tutor.vim
+++ b/runtime/ftplugin/tutor.vim
@@ -19,27 +19,30 @@ setlocal noundofile
setlocal keywordprg=:help
setlocal iskeyword=@,-,_
-setlocal foldmethod=expr
+" The user will have to enable the folds himself, but we provide the foldexpr
+" function.
+setlocal foldmethod=manual
setlocal foldexpr=tutor#TutorFolds()
-setlocal foldcolumn=1
setlocal foldlevel=4
-setlocal nowrap
setlocal statusline=%{toupper(expand('%:t:r'))}\ tutorial%=
setlocal statusline+=%{tutor#InfoText()}
+" Load metadata if it exists: {{{1
+if filereadable(expand('%').'.json')
+ call tutor#LoadMetadata()
+endif
+
" Mappings: {{{1
call tutor#SetNormalMappings()
-call tutor#SetSampleTextMappings()
" Checks: {{{1
sign define tutorok text=✓ texthl=tutorOK
sign define tutorbad text=✗ texthl=tutorX
-if !exists('g:tutor_debug') || g:tutor_debug == 0
- call tutor#PlaceXMarks()
- autocmd! TextChanged <buffer> call tutor#OnTextChanged()
- autocmd! TextChangedI <buffer> call tutor#OnTextChanged()
+if !exists('g:tutor_debug') || g:tutor_debug == 0
+ call tutor#ApplyMarks()
+ autocmd! TextChanged,TextChangedI <buffer> call tutor#ApplyMarksOnChanged()
endif
diff --git a/runtime/syntax/tutor.vim b/runtime/syntax/tutor.vim
index bce9189660..fbf159582a 100644
--- a/runtime/syntax/tutor.vim
+++ b/runtime/syntax/tutor.vim
@@ -31,26 +31,20 @@ syn keyword tutorMarks TODO NOTE IMPORTANT TIP ATTENTION EXERCISE
syn keyword tutorMarks todo note tip attention exercise
syn keyword tutorMarks Todo Note Tip Excersise
-syn match tutorTextMark /\\\@<!--->/ conceal cchar=→
-syn region tutorSampleText start=/^\(--->\)\@=/ end=/$/ keepend contains=@SPELL
-syn match tutorSampleTextMark /^--->/ contained containedin=tutorSampleText conceal cchar=→
-syn match tutorSampleTextExpect /\}\@<! {expect:.\+}\s*$/ contained containedin=tutorSampleText conceal
-syn match tutorSampleTextExpect /|\@<! |expect:.\+|\s*$/ contained containedin=tutorSampleText conceal
-
syn region tutorCodeblock matchgroup=Delimiter start=/^\~\{3}.*$/ end=/^\~\{3}/
-syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL concealends
+syn region tutorShell matchgroup=Delimiter start=/^\~\{3} sh\s*$/ end=/^\~\{3}/ keepend contains=@TUTORSHELL
syn match tutorShellPrompt /\(^\s*\)\@<=[$#]/ contained containedin=tutorShell
-syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/ concealends
+syn region tutorInlineCode matchgroup=Delimiter start=/\\\@<!`/ end=/\\\@<!\(`{\@!\|`\s\)/
-syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM concealends
-syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM concealends
+syn region tutorCommand matchgroup=Delimiter start=/^\~\{3} cmd\( :\)\?\s*$/ end=/^\~\{3}/ keepend contains=@VIM
+syn region tutorInlineCommand matchgroup=Delimiter start=/\\\@<!`\(.*{vim}\)\@=/ end=/\\\@<!`\({vim}\)\@=/ nextgroup=tutorInlineType contains=@VIM
-syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL concealends
-syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL concealends
+syn region tutorNormal matchgroup=Delimiter start=/^\~\{3} norm\(al\?\)\?\s*$/ end=/^\~\{3}/ contains=@VIMNORMAL
+syn region tutorInlineNormal matchgroup=Delimiter start=/\\\@<!`\(\S*{normal}\)\@=/ end=/\\\@<!`\({normal}\)\@=/ nextgroup=tutorInlineType contains=@VIMNORMAL
-syn match tutorInlineType /{\(normal\|vim\)}/ contained conceal
+syn match tutorInlineType /{\(normal\|vim\)}/ contained
syn match tutorInlineOK /✓/
syn match tutorInlineX /✗/
@@ -72,7 +66,7 @@ hi! tutorMarks cterm=bold gui=bold
hi! tutorEmphasis gui=italic cterm=italic
hi! tutorBold gui=bold cterm=bold
-hi! link tutorSampleText Special
+hi! link tutorExpect Special
hi! tutorOK ctermfg=green guifg=#00ff88 cterm=bold gui=bold
hi! tutorX ctermfg=red guifg=#ff2000 cterm=bold gui=bold
hi! link tutorInlineOK tutorOK
diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor
index 47d4ed06a1..fee7de21d2 100644
--- a/runtime/tutor/en/vim-01-beginner.tutor
+++ b/runtime/tutor/en/vim-01-beginner.tutor
@@ -18,10 +18,10 @@ be saved. Don't worry about messing things up; just remember that pressing
[<Esc>](<Esc>) and then [u](u) will undo the latest change.
This tutorial is interactive, and there are a few things you should know.
-Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some relevant
-help (hopefully), and pressing K over any word will try to do so too. Sometimes
-you will be required to modify text like
----> this here {expect:this here}
+Pressing [<Enter>](<Enter>) over text highlighted [like this](holy-grail) will take you to some
+relevant help (hopefully), and pressing K over any word will try to do so too.
+Sometimes you will be required to modify text like
+this here
Once you have done the changes correctly, the ✗ sign at the left will change
to ✓. I imagine you can already see how neat Vim can be ;)
Other times, you'll be prompted to run a command (I'll explain this later):
@@ -99,7 +99,7 @@ NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
4. Repeat steps 2 through 4 until the sentence is correct.
----> The ccow jumpedd ovverr thhe mooon. {expect:The cow jumped over the moon.}
+The ccow jumpedd ovverr thhe mooon.
5. Now that the line is correct, go on to Lesson 1.4.
@@ -119,8 +119,8 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage.
4. As each error is fixed press <Esc> to return to Normal mode.
Repeat steps 2 through 4 to correct the sentence.
----> There is text misng this . {expect:There is some text missing from this line.}
----> There is some text missing from this line. {expect:There is some text missing from this line.}
+There is text misng this .
+There is some text missing from this line.
5. When you are comfortable inserting text move to lesson 1.5.
@@ -138,10 +138,10 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage.
4. Move the cursor to the second line marked ---> and repeat
steps 2 and 3 to correct this sentence.
----> There is some text missing from th {expect:There is some text missing from this line.}
----> There is some text missing from this line. {expect:There is some text missing from this line.}
----> There is also some text miss {expect:There is also some text missing here.}
----> There is also some text missing here. {expect:There is also some text missing here.}
+There is some text missing from th
+There is some text missing from this line.
+There is also some text miss
+There is also some text missing here.
5. When you are comfortable appending text move to lesson 1.6.
@@ -212,7 +212,7 @@ Now continue with Lesson 2.
4. Type [d](d)[w](w) to make the word disappear.
----> There are a some words fun that don't belong paper in this sentence. {expect:There are some words that don't belong in this sentence.}
+There are a some words fun that don't belong paper in this sentence.
5. Repeat steps 3 and 4 until the sentence is correct and go to Lesson 2.2.
@@ -228,7 +228,7 @@ Now continue with Lesson 2.
4. Type `d$`{normal} to delete to the end of the line.
----> Somebody typed the end of this line twice. end of this line twice. {expect:ANYTHING}
+Somebody typed the end of this line twice. end of this line twice.
5. Move on to Lesson 2.3 to understand what is happening.
@@ -268,7 +268,7 @@ NOTE: Pressing just the motion while in Normal mode without an operator will
5. Repeat steps 2 and 3 with different numbers.
----> This is just a line with words you can move around in. {expect:ANYTHING}
+This is just a line with words you can move around in.
6. Move on to Lesson 2.5.
@@ -287,7 +287,7 @@ insert a count before the motion to delete more:
3. Repeat steps 1 and 2 with a different count to delete the consecutive
UPPER CASE words with one command
----> this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up. {expect:this line of words is cleaned up.}
+this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
# Lesson 2.6: OPERATING ON LINES
@@ -301,13 +301,13 @@ insert a count before the motion to delete more:
3. Now move to the fourth line.
4. Type `2dd`{normal} to delete two lines.
----> 1) Roses are red, {expect:ANYTHING}
----> 2) Mud is fun, {expect:ANYTHING}
----> 3) Violets are blue, {expect:ANYTHING}
----> 4) I have a car, {expect:ANYTHING}
----> 5) Clocks tell time, {expect:ANYTHING}
----> 6) Sugar is sweet {expect:ANYTHING}
----> 7) And so are you. {expect:ANYTHING}
+1) Roses are red,
+2) Mud is fun,
+3) Violets are blue,
+4) I have a car,
+5) Clocks tell time,
+6) Sugar is sweet
+7) And so are you.
# Lesson 2.7: THE UNDO COMMAND
@@ -322,7 +322,7 @@ insert a count before the motion to delete more:
6. Now type `u`{normal} a few times to undo the U and preceding commands.
7. Now type `<Ctrl-r>`{normal} a few times to redo the commands (undo the undo's).
----> Fiix the errors oon thhis line and reeplace them witth undo. {expect:Fix the errors on this line and replace them with undo.}
+Fiix the errors oon thhis line and reeplace them witth undo.
8. These are very useful commands. Now move on to the Lesson 2 Summary.
@@ -362,10 +362,10 @@ insert a count before the motion to delete more:
5. Repeat steps 2 through 4 to put all the lines in correct order.
----> d) Can you learn too? {expect:ANYTHING}
----> b) Violets are blue, {expect:ANYTHING}
----> c) Intelligence is learned, {expect:ANYTHING}
----> a) Roses are red, {expect:ANYTHING}
+d) Can you learn too?
+b) Violets are blue,
+c) Intelligence is learned,
+a) Roses are red,
# Lesson 3.2: THE REPLACE COMMAND
@@ -379,8 +379,8 @@ insert a count before the motion to delete more:
4. Repeat steps 2 and 3 until the first line is equal to the second one.
----> Whan this lime was tuoed in, someone presswd some wrojg keys! {expect:When this line was typed in, someone pressed some wrong keys!}
----> When this line was typed in, someone pressed some wrong keys! {expect:When this line was typed in, someone pressed some wrong keys!}
+Whan this lime was tuoed in, someone presswd some wrojg keys!
+When this line was typed in, someone pressed some wrong keys!
5. Now move on to Lesson 3.3.
@@ -400,8 +400,8 @@ NOTE: Remember that you should be learning by doing, not memorization.
5. Repeat steps 3 and 4 until the first sentence is the same as the second.
----> This lubw has a few wptfd that mrrf changing usf the change operator. {expect:This line has a few words that need changing using the change operator.}
----> This line has a few words that need changing using the change operator. {expect:This line has a few words that need changing using the change operator.}
+This lubw has a few wptfd that mrrf changing usf the change operator.
+This line has a few words that need changing using the change operator.
Notice that [c](c)e deletes the word and places you in Insert mode.
@@ -421,8 +421,8 @@ Notice that [c](c)e deletes the word and places you in Insert mode.
5. Type `c$`{normal} and type the rest of the line like the second and press `<Esc>`{normal}.
----> The end of this line needs some help to make it like the second. {expect:The end of this line needs to be corrected using the c$ command.}
----> The end of this line needs to be corrected using the c$ command. {expect:The end of this line needs to be corrected using the c$ command.}
+The end of this line needs some help to make it like the second.
+The end of this line needs to be corrected using the c$ command.
NOTE: You can use the Backspace key to correct mistakes while typing.
@@ -484,7 +484,7 @@ NOTE: You may see the cursor position in the lower right corner of the screen
5. To go back to where you came from press `<Ctrl-o>`{normal} (Keep Ctrl down while
pressing the letter o). Repeat to go back further. `<Ctrl-i>`{normal} goes forward.
----> "errroor" is not the way to spell error; errroor is an error. {expect:ANYTHING}
+"errroor" is not the way to spell error; errroor is an error.
NOTE: When the search reaches the end of the file it will continue at the
start, unless the ['wrapscan']('wrapscan') option has been reset.
@@ -503,7 +503,7 @@ NOTE: When the search reaches the end of the file it will continue at the
5. Move the cursor to another (,),[,],{ or } and see what `%`{normal} does.
----> This ( is a test line with ('s, ['s ] and {'s } in it. )) {expect:ANYTHING}
+This ( is a test line with ('s, ['s ] and {'s } in it. ))
NOTE: This is very useful in debugging a program with unmatched parentheses!
@@ -528,7 +528,7 @@ NOTE: This is very useful in debugging a program with unmatched parentheses!
Adding the g [flag](:s_flags) means to substitute globally in the line, change
all occurrences of "thee" in the line.
----> thee best time to see thee flowers is in thee spring. {expect:the best time to see the flowers is in the spring.}
+thee best time to see thee flowers is in thee spring.
4. To change every occurrence of a character string between two lines, type
~~~ cmd
@@ -719,12 +719,12 @@ NOTE: You can also read the output of an external command. For example,
3. Now type some text and press `<Esc>`{normal} to exit Insert mode.
----> After typing o the cursor is placed on the open line in Insert mode. {expect:ANYTHING}
+After typing o the cursor is placed on the open line in Insert mode.
4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather
than a lowercase `o`{normal}. Try this on the line below.
----> Open up a line above this by typing O while the cursor is on this line. {expect:ANYTHING}
+Open up a line above this by typing O while the cursor is on this line.
# Lesson 6.2: THE APPEND COMMAND
@@ -741,8 +741,8 @@ NOTE: You can also read the output of an external command. For example,
5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4.
----> This li will allow you to pract appendi text to a line. {expect:This line will allow you to practice appending text to a line.}
----> This line will allow you to practice appending text to a line. {expect:This line will allow you to practice appending text to a line.}
+This li will allow you to pract appendi text to a line.
+This line will allow you to practice appending text to a line.
NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only difference is where
the characters are inserted.
@@ -762,8 +762,8 @@ NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only differ
4. Repeat the steps to replace the remaining "xxx".
----> Adding 123 to xxx gives you xxx. {expect:Adding 123 to 456 gives you 579.}
----> Adding 123 to 456 gives you 579. {expect:Adding 123 to 456 gives you 579.}
+Adding 123 to xxx gives you xxx.
+Adding 123 to 456 gives you 579.
NOTE: Replace mode is like Insert mode, but every typed character deletes an
existing character.
@@ -785,8 +785,8 @@ NOTE: Replace mode is like Insert mode, but every typed character deletes an
6. Use Visual mode to select " item.", yank it with `y`{normal}, move to the end of
the next line with `j$`{normal} and put the text there with `p`{normal}.
----> a) this is the first item.
----> b) {expect: b) this is the second item}
+a) this is the first item.
+ b)
NOTE: you can also use `y`{normal} as an operator; `yw`{normal} yanks one word.
@@ -947,8 +947,10 @@ There are many resources online to learn more about vim. Here's a bunch of them:
- Vim Video-Tutorials by Derek Wyatt: http://derekwyatt.org/vim/tutorials/
- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/
- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html
+- *vim-galore*: https://github.com/mhinz/vim-galore
-If you prefer a book, *Practival Vim* by Drew Neil is recommended often.
+If you prefer a book, *Practical Vim* by Drew Neil is recommended often (the sequel, *Modern
+Vim*, includes material specific to nvim!).
This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado
School of Mines using ideas supplied by Charles Smith, Colorado State
diff --git a/runtime/tutor/en/vim-01-beginner.tutor.json b/runtime/tutor/en/vim-01-beginner.tutor.json
new file mode 100644
index 0000000000..3f55971a09
--- /dev/null
+++ b/runtime/tutor/en/vim-01-beginner.tutor.json
@@ -0,0 +1,45 @@
+{
+ "expect": {
+ "24": -1,
+ "102": "The cow jumped over the moon.",
+ "122": "There is some text missing from this line.",
+ "123": "There is some text missing from this line.",
+ "141": "There is some text missing from this line.",
+ "142": "There is some text missing from this line.",
+ "143": "There is also some text missing here.",
+ "144": "There is also some text missing here.",
+ "215": "There are some words that don't belong in this sentence.",
+ "231": "Somebody typed the end of this line twice.",
+ "271": -1,
+ "290": "this line of words is cleaned up.",
+ "304": -1,
+ "305": -1,
+ "306": -1,
+ "307": -1,
+ "308": -1,
+ "309": -1,
+ "310": -1,
+ "325": "Fix the errors on this line and replace them with undo.",
+ "365": -1,
+ "366": -1,
+ "367": -1,
+ "368": -1,
+ "382": "When this line was typed in, someone pressed some wrong keys!",
+ "383": "When this line was typed in, someone pressed some wrong keys!",
+ "403": "This line has a few words that need changing using the change operator.",
+ "404": "This line has a few words that need changing using the change operator.",
+ "424": "The end of this line needs to be corrected using the c$ command.",
+ "425": "The end of this line needs to be corrected using the c$ command.",
+ "487": -1,
+ "506": -1,
+ "531": "the best time to see the flowers is in the spring.",
+ "722": -1,
+ "727": -1,
+ "744": "This line will allow you to practice appending text to a line.",
+ "745": "This line will allow you to practice appending text to a line.",
+ "765": "Adding 123 to 456 gives you 579.",
+ "766": "Adding 123 to 456 gives you 579.",
+ "788": "a) this is the first item.",
+ "789": " b) this is the second item."
+ }
+}
diff --git a/runtime/tutor/tutor.tutor b/runtime/tutor/tutor.tutor
index 1ad64a18ff..c937bd686a 100644
--- a/runtime/tutor/tutor.tutor
+++ b/runtime/tutor/tutor.tutor
@@ -60,27 +60,27 @@ is displayed like
1. Format the line below so it becomes a lesson description:
----> This is text with important information {expect:This is text with **important information**}
----> This is text with **important information** {expect:This is text with **important information**}
+This is text with important information
+This is text with **important information**
Note: Some words (e.g., NOTE, IMPORTANT, tip, ATTENTION, etc.) will also be
highlighted. You don't need to mark them specially.
2. Turn the line below into a TODO item:
----> Document '&variable' {expect:TODO: Document '&variable'}
----> TODO: Document '&variable' {expect:TODO: Document '&variable'}
+Document '&variable'
+TODO: Document '&variable'
### Headers *headers*
3. Practice fixing the lines below:
----> This is a level 1 header {expect:# This is a level 1 header}
----> # This is a level 1 header {expect:# This is a level 1 header}
----> This is a level 3 header {expect:### This is a level 3 header}
----> ### This is a level 3 header {expect:### This is a level 3 header}
----> This is a header with a label {expect:# This is a header with a label {*label*}}
----> # This is a header with a label {*label*} {expect:# This is a header with a label {*label*}}
+This is a level 1 header
+# This is a level 1 header
+This is a level 3 header
+### This is a level 3 header
+This is a header with a label
+# This is a header with a label {*label*}
4. Now, create a 4th level section here, and add a label like in the previous
exercise:
@@ -105,8 +105,8 @@ If the target of a link matches a help topic, opening it will open it.
5. Fix the following line:
----> A link to help for the 'breakindent' option {expect:A link to help for the ['breakindent']('breakindent') option}
----> A link to help for the ['breakindent']('breakindent') option {expect:A link to help for the ['breakindent']('breakindent') option}
+A link to help for the 'breakindent' option
+A link to help for the ['breakindent']('breakindent') option
#### Anchor links
@@ -120,8 +120,8 @@ and are hidden by default. Links to them look like
6. Add the appropiate link:
----> A link to the Links section {expect:A link to the [Links](*links*) section}
----> A link to the [Links](*links*) section {expect:A link to the [Links](*links*) section}
+A link to the Links section
+A link to the [Links](*links*) section
7. Now, create a link to the section you created on exercise 4
above.
@@ -136,8 +136,8 @@ You can also have links to other tutorials. For this, you'll write the anchor in
7. Create a link to this tutorial:
----> A link to the vim-tutor-mode tutorial {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)}
----> A link to [the vim-tutor-mode tutorial](@tutor:tutor) {expect:A link to [the vim-tutor-mode tutorial](@tutor:tutor)}
+A link to the vim-tutor-mode tutorial
+A link to [the vim-tutor-mode tutorial](@tutor:tutor)
### Codeblocks *codeblocks*
@@ -154,13 +154,13 @@ echom "hello"
8. Copy the viml section below
----> {expect:~~~ viml}
----> {expect:echom "the value of &number is".string(&number)}
----> {expect:~~~}
----> ~~~ viml {expect:~~~ viml}
----> echom "the value of &number is".string(&number) {expect:echom "the value of &number is".string(&number)}
----> ~~~ {expect:~~~}
+
+
+
+~~~ viml
+echom 'the value of &number is'.string(&number)
+~~~
You can inline viml code using "\`" and "\`{vim}":
@@ -185,13 +185,13 @@ Note: you can also write `norm` or `normal`.
9. Copy the normal section below
----> {expect:~~~ normal}
----> {expect:d2w}
----> {expect:~~~}
----> ~~~ normal {expect:~~~ normal}
----> d2w {expect:d2w}
----> ~~~ {expect:~~~}
+
+
+
+~~~ normal
+d2w
+~~~
You can also inline normal commands by using "\`" and "\`{normal}":
@@ -203,10 +203,11 @@ is displayed:
10. Complete the line as shown
----> d {expect:«d2w»}
----> «d2w» {expect:«d2w»}
+d
+`d2w`{normal}
-Commands to run in the system shell can be highlighted by indenting a line starting with "$".
+Commands to run in the system shell can be highlighted by indenting a line
+starting with "$".
~~~ sh
$ vim --version
@@ -215,45 +216,32 @@ Commands to run in the system shell can be highlighted by indenting a line start
## INTERACTIVE ELEMENTS *interactive*
As visible in this very document, vim-tutor-mode includes some interactive
-elements, to provide feedback to the user about his progress. These elements
-all have the syntax
-
- \---> TEXT {CLAUSE}
-
-where \---> must start at the beginning of the line. If TEXT satisfies CLAUSE,
-a ✓ sign will appear to the left. A ✗ sign is displayed otherwise. The CLAUSE
-itself is hidden unless debug mode is set or ['conceallevel']('conceallevel')
-is 2.
+elements to provide feedback to the user about his progress. If the text in
+these elements satisfies some set condition, a ✓ sign will appear in the gutter
+to the left. Otherwise, a ✗ sign is displayed.
### expect *expect*
-The basic clause is "expect", which is satisfied if TEXT is the same as the
-content of the clause. For example
-
- \---> TEXT {expect:TEXT}
-
-is satisfied, but
-
- \---> OTHER TEXT {expect:TEXT}
-
-is not.
+"expect" lines check that the contents of the line are identical to some preset text
+(like in the exercises above).
-13. Make both lines the same:
+These elements are specified in separate JSON files like this
----> this is not right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}|
----> ---> this is right {expect:---> this is right} |expect:---> this is right {expect:---> this is right}|
-
-
-If the content of a expect clause is ANYTHING, no checks will be performed. This is
-useful to create a line that is highlighted you want the user to play with.
-
- \---> TEXT {expect:ANYTHING}
-
-is displayed
+~~~ json
+{
+ "expect": {
+ "1": "This is how this line should look.",
+ "2": "This is how this line should look.",
+ "3": -1
+ }
+}
+~~~
----> this is free text {expect:ANYTHING}
+These files contain an "expect" dictionary, for which the keys are line numbers and
+the values are the expected text. A value of -1 means that the condition for the line
+will always be satisfied, no matter what (this is useful for letting the user play a bit).
-14. Turn the line below into free text:
+This is an "expect" line that is always satisfied. Try changing it.
----> this is some text |expect:---> this is some text {expect:ANYTHING}|
----> ---> this is some text {expect:ANYTHING} |expect:---> this is some text {expect:ANYTHING}|
+These files conventionally have the same name as the tutorial document with the `.json`
+extension appended (for a full example, see the file that corresponds to this tutorial).
diff --git a/runtime/tutor/tutor.tutor.json b/runtime/tutor/tutor.tutor.json
new file mode 100644
index 0000000000..bf3eae8586
--- /dev/null
+++ b/runtime/tutor/tutor.tutor.json
@@ -0,0 +1,35 @@
+{
+ "expect": {
+ "63": "This is text with **important information**",
+ "64": "This is text with **important information**",
+ "71": "Document '&variable'",
+ "72": "Document '&variable'",
+ "78": "# This is a level 1 header",
+ "79": "# This is a level 1 header",
+ "80": "### This is a level 3 header",
+ "81": "### This is a level 3 header",
+ "82": "# This is a header with a label {*label*}",
+ "83": "# This is a header with a label {*label*}",
+ "108": "A link to help for the ['breakindent']('breakindent') option",
+ "109": "A link to help for the ['breakindent']('breakindent') option",
+ "123": "A link to the [Links](*links*) section",
+ "124": "A link to the [Links](*links*) section",
+ "139": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
+ "140": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
+ "157": "~~~ viml",
+ "158": "echom 'the value of &number is'.string(&number)",
+ "159": "~~~",
+ "161": "~~~ viml",
+ "162": "echom 'the value of &number is'.string(&number)",
+ "163": "~~~",
+ "188": "~~~ normal",
+ "189": "d2w",
+ "190": "~~~",
+ "192": "~~~ normal",
+ "193": "d2w",
+ "194": "~~~",
+ "206": "`d2w`{normal}",
+ "207": "`d2w`{normal}",
+ "244": -1
+ }
+}