From 2dc5b141dab679784b6bde3e15baffa135a56019 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Thu, 13 Jul 2017 17:20:06 -0400 Subject: [PATCH 1/7] tutor: some tweaks to begginer's tutorial --- runtime/tutor/en/vim-01-beginner.tutor | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index 47d4ed06a1..e88603fedb 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor +++ b/runtime/tutor/en/vim-01-beginner.tutor @@ -18,9 +18,9 @@ be saved. Don't worry about messing things up; just remember that pressing []() and then [u](u) will undo the latest change. This tutorial is interactive, and there are a few things you should know. -Pressing []() 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 +Pressing []() 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} 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 ;) @@ -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 From ec67d0706524a23768c8a964a7940a34f057edb8 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Thu, 13 Jul 2017 19:04:15 -0400 Subject: [PATCH 2/7] tutor: allow metadata to exist outside of the documents. this makes 'expect' regions simpler to handle. --- runtime/autoload/tutor.vim | 46 ++++++++++- runtime/ftplugin/tutor.vim | 21 ++++-- runtime/tutor/en/vim-01-beginner.tutor | 84 ++++++++++----------- runtime/tutor/en/vim-01-beginner.tutor.json | 49 ++++++++++++ 4 files changed, 151 insertions(+), 49 deletions(-) create mode 100644 runtime/tutor/en/vim-01-beginner.tutor.json diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index 43d8a87886..1f0668c1b3 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -209,7 +209,15 @@ function! tutor#InfoText() return join(l:info_parts, " ") endfunction -" Marks {{{1 +function! tutor#LoadMetadata() + try + let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n")) + catch + endtry +endfunction + +" Marks: {{{1 +" Internal: {{{2 function! tutor#PlaceXMarks() call cursor(1, 1) let b:tutor_sign_id = 1 @@ -241,13 +249,47 @@ function! tutor#CheckText(text) endif endfunction -function! tutor#OnTextChanged() +function! tutor#XmarksOnTextChanged() let l:text = getline('.') if match(l:text, '^--->') > -1 call tutor#CheckText(l:text) endif endfunction +" External: {{{2 +function! tutor#ApplyMarks() + 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('tutorSampleText', [lnum]) + call tutor#CheckLine(lnum) + endfor + endif +endfunction + +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#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 + " Tutor Cmd: {{{1 function! s:Locale() diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim index 1579753170..4cfde4c2df 100644 --- a/runtime/ftplugin/tutor.vim +++ b/runtime/ftplugin/tutor.vim @@ -28,18 +28,29 @@ 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() +if exists('b:tutor_metadata') && b:tutor_metadata['settings']['use_maps'] == 1 + call tutor#SetSampleTextMappings() +endif " 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 call tutor#OnTextChanged() - autocmd! TextChangedI call tutor#OnTextChanged() +if !exists('g:tutor_debug') || g:tutor_debug == 0 + if !(exists('b:tutor_metadata') && b:tutor_metadata['settings']['check_internal_expects'] == '0') + call tutor#PlaceXMarks() + autocmd! TextChanged,TextChangedI call tutor#XmarksOnTextChanged() + else + call tutor#ApplyMarks() + autocmd! TextChanged,TextChangedI call tutor#ApplyMarksOnChanged() + endif endif diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor index e88603fedb..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 []() and then [u](u) will undo the latest change. This tutorial is interactive, and there are a few things you should know. -Pressing []() over text highlighted [like this](holy-grail) will take you to some +Pressing []() 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} +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) 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 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 ``{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 ``{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 ``{normal} (Keep Ctrl down while pressing the letter o). Repeat to go back further. ``{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 ``{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. 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..5bf50581ab --- /dev/null +++ b/runtime/tutor/en/vim-01-beginner.tutor.json @@ -0,0 +1,49 @@ +{ + "settings" : { + "use_maps": 0, + "check_internal_expects": 0 + }, + "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." + } +} From c235ee3f059d43a6099d7983b68b433abdd7e395 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Thu, 14 Jul 2016 23:38:47 +0200 Subject: [PATCH 3/7] tutor: don't enable folds by default --- runtime/ftplugin/tutor.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim index 4cfde4c2df..660c1afaf5 100644 --- a/runtime/ftplugin/tutor.vim +++ b/runtime/ftplugin/tutor.vim @@ -19,11 +19,11 @@ 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()} From cb0282ad986e5b496aa89e3a78984a1307344ff4 Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Fri, 14 Jul 2017 19:31:47 -0400 Subject: [PATCH 4/7] tutor: update tutor-mode tutorial --- runtime/tutor/tutor.tutor | 118 +++++++++++++++------------------ runtime/tutor/tutor.tutor.json | 35 ++++++++++ 2 files changed, 88 insertions(+), 65 deletions(-) create mode 100644 runtime/tutor/tutor.tutor.json 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 +"expect" lines check that the contents of the line are identical to some preset text +(like in the exercises above). - \---> TEXT {expect:TEXT} +These elements are specified in separate JSON files like this -is satisfied, but +~~~ json +{ + "expect": { + "1": "This is how this line should look.", + "2": "This is how this line should look.", + "3": -1 + } +} +~~~ - \---> OTHER TEXT {expect:TEXT} +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). -is not. +This is an "expect" line that is always satisfied. Try changing it. -13. Make both lines the same: - ----> 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 - ----> this is free text {expect:ANYTHING} - -14. Turn the line below into free text: - ----> 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 + } +} From 8e48d7c19e0a01d17fbda1c21a8fa69c039cec7a Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Thu, 13 Jul 2017 19:02:53 -0400 Subject: [PATCH 5/7] tutor: disable old method for setting "expect" regions tutor: remove movement mappings --- runtime/autoload/tutor.vim | 163 -------------------- runtime/ftplugin/tutor.vim | 12 +- runtime/tutor/en/vim-01-beginner.tutor.json | 4 - 3 files changed, 2 insertions(+), 177 deletions(-) diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index 1f0668c1b3..2217fabeda 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -17,30 +17,6 @@ endfunction " Mappings: {{{1 -function! s:CheckMaps() - nmap -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 ".a:key." ".a:cmd - return - endif - let l:map_data = split(l:raw_map[0], '\s*') - - exe "nnoremap ".l:map_data[0]." ".a:cmd - else - exe "nnoremap ".a:key." ".a:cmd - endif -endfunction - function! tutor#MouseDoubleClick() if foldclosed(line('.')) > -1 normal! zo @@ -60,111 +36,11 @@ function! tutor#InjectCommand() endfunction function! tutor#SetNormalMappings() - call s:MapKeyWithRedirect('l', 'tutor#ForwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('h', 'tutor#BackwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('', 'tutor#ForwardSkipConceal(v:count1)') - call s:MapKeyWithRedirect('', 'tutor#BackwardSkipConceal(v:count1)') - nnoremap :call tutor#FollowLink(0) nnoremap <2-LeftMouse> :call tutor#MouseDoubleClick() nnoremap >> :call tutor#InjectCommand() endfunction -function! tutor#SetSampleTextMappings() - noremap A :if match(getline('.'), '^--->') > -1 \| call search('\s{\@=', 'Wc') \| startinsert \| else \| startinsert! \| endif - noremap $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif - onoremap $ :if match(getline('.'), '^--->') > -1 \| call search('.\s{\@=', 'Wc') \| else \| call search('$', 'Wc') \| endif - noremap ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif - onoremap ^ :if match(getline('.'), '^--->') > -1 \| call search('\(--->\s\)\@<=.', 'bcW') \| else \| call search('^', 'bcW') \|endif - nmap 0 ^ - nmap ^ - nmap $ - imap ^:startinsert - imap $:startinsert - noremap I :exe "normal! 0" \| startinsert -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) @@ -217,46 +93,7 @@ function! tutor#LoadMetadata() endfunction " Marks: {{{1 -" Internal: {{{2 -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) -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 - endif - endif -endfunction - -function! tutor#XmarksOnTextChanged() - let l:text = getline('.') - if match(l:text, '^--->') > -1 - call tutor#CheckText(l:text) - endif -endfunction - -" External: {{{2 function! tutor#ApplyMarks() if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect') let b:tutor_sign_id = 1 diff --git a/runtime/ftplugin/tutor.vim b/runtime/ftplugin/tutor.vim index 660c1afaf5..ec55472b78 100644 --- a/runtime/ftplugin/tutor.vim +++ b/runtime/ftplugin/tutor.vim @@ -36,9 +36,6 @@ endif " Mappings: {{{1 call tutor#SetNormalMappings() -if exists('b:tutor_metadata') && b:tutor_metadata['settings']['use_maps'] == 1 - call tutor#SetSampleTextMappings() -endif " Checks: {{{1 @@ -46,11 +43,6 @@ sign define tutorok text=✓ texthl=tutorOK sign define tutorbad text=✗ texthl=tutorX if !exists('g:tutor_debug') || g:tutor_debug == 0 - if !(exists('b:tutor_metadata') && b:tutor_metadata['settings']['check_internal_expects'] == '0') - call tutor#PlaceXMarks() - autocmd! TextChanged,TextChangedI call tutor#XmarksOnTextChanged() - else - call tutor#ApplyMarks() - autocmd! TextChanged,TextChangedI call tutor#ApplyMarksOnChanged() - endif + call tutor#ApplyMarks() + autocmd! TextChanged,TextChangedI call tutor#ApplyMarksOnChanged() endif diff --git a/runtime/tutor/en/vim-01-beginner.tutor.json b/runtime/tutor/en/vim-01-beginner.tutor.json index 5bf50581ab..3f55971a09 100644 --- a/runtime/tutor/en/vim-01-beginner.tutor.json +++ b/runtime/tutor/en/vim-01-beginner.tutor.json @@ -1,8 +1,4 @@ { - "settings" : { - "use_maps": 0, - "check_internal_expects": 0 - }, "expect": { "24": -1, "102": "The cow jumped over the moon.", From 37af8599307819c66da287ed3cb0babf6295dbfc Mon Sep 17 00:00:00 2001 From: Felipe Morales Date: Fri, 14 Jul 2017 19:46:31 -0400 Subject: [PATCH 6/7] tutor: update syntax sampletext regions no longer supported make sure tutorExpect is available don't conceal code region delimiters --- runtime/autoload/tutor.vim | 3 ++- runtime/syntax/tutor.vim | 22 ++++++++-------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index 2217fabeda..c03326c7fb 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -95,11 +95,12 @@ endfunction " 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('tutorSampleText', [lnum]) + call matchaddpos('tutorExpect', [lnum]) call tutor#CheckLine(lnum) endfor 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 /\}\@ Date: Sat, 15 Jul 2017 09:14:26 -0400 Subject: [PATCH 7/7] tutor: reorganize --- runtime/autoload/tutor.vim | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim index c03326c7fb..56e2283465 100644 --- a/runtime/autoload/tutor.vim +++ b/runtime/autoload/tutor.vim @@ -15,14 +15,25 @@ function! tutor#SetupVim() endif endfunction +" Loads metadata file, if available +function! tutor#LoadMetadata() + let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n")) +endfunction + " Mappings: {{{1 +function! tutor#SetNormalMappings() + nnoremap :call tutor#FollowLink(0) + nnoremap <2-LeftMouse> :call tutor#MouseDoubleClick() + nnoremap >> :call tutor#InjectCommand() +endfunction + function! tutor#MouseDoubleClick() if foldclosed(line('.')) > -1 normal! zo else if match(getline('.'), '^#\{1,} ') > -1 - normal! zc + silent normal! zc else call tutor#FollowLink(0) endif @@ -35,14 +46,6 @@ function! tutor#InjectCommand() redraw | echohl WarningMsg | echon "tutor: ran" | echohl None | echon " " | echohl Statement | echon l:cmd endfunction -function! tutor#SetNormalMappings() - nnoremap :call tutor#FollowLink(0) - nnoremap <2-LeftMouse> :call tutor#MouseDoubleClick() - nnoremap >> :call tutor#InjectCommand() -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' @@ -85,12 +88,6 @@ function! tutor#InfoText() return join(l:info_parts, " ") endfunction -function! tutor#LoadMetadata() - try - let b:tutor_metadata = json_decode(join(readfile(expand('%').'.json'), "\n")) - catch - endtry -endfunction " Marks: {{{1