Commits

khorser committed a805d1a

Initial check-in

Comments (0)

Files changed (3)

autoload/repl.vim

+" REPL plugin to interact with interpreters for various programming languages
+" Author: Sergey Khorev <sergey.khorev@gmail.com>
+" Last Change:	$HGLastChangedDate$
+
+let s:ReplFullyInitialized = 0
+
+function! s:ReplInit2()
+  if s:ReplFullyInitialized
+    return
+  endif
+  try
+    call vimproc#version()
+  catch
+    echoerr 'Error running vimproc:' v:exception '. Is it installed?'
+    return
+  endtry
+
+  let s:ReplFullyInitialized = 1
+  augroup REPL
+    " TODO setup more autocommand for async updates
+    autocmd CursorHold * call <SID>ReadFromRepl()
+  augroup END
+
+  vnoremap <silent> <Plug>EvalSelection :call <SID>EvalSelection()<cr>
+  nnoremap <silent> <Plug>EvalLine :call <SID>EvalLine()<cr>
+
+  if !hasmapto('<Plug>EvalSelection')
+    vmap <unique> <silent> <Leader>e <Plug>EvalSelection
+  endif
+  if !hasmapto('<Plug>EvalLine')
+    nmap <unique> <silent> <Leader>e <Plug>EvalLine
+  endif
+endfunction
+
+function! s:SetupBuffer()
+  setlocal bufhidden=hide buftype=nofile noswapfile
+  "setlocal nobuflisted
+  exec 'silent file' bufnr('').b:replinfo.type
+  setlocal filetype=repl
+
+  nmap <buffer> <silent> <Return> :call <SID>Execute()<cr>
+  nmap <buffer> <silent> <C-J> :call <SID>CopyCurrent()<cr>
+  " start of the current or prev command
+  nmap <buffer> <silent> [[ :<C-U>call <SID>EndOfCurrOrPrevPromptMap()<cr>
+  " start of the next command
+  nmap <buffer> <silent> ]] :<C-U>call <SID>EndOfNextPromptMap()<cr>
+  " end of prev command
+  nmap <buffer> <silent> [] :<C-U>call <SID>GoToEndOfPrevCommandMap()<cr>
+  " end of curr or next command
+  nmap <buffer> <silent> ][ :<C-U>call <SID>GoToEndOfNextOrCurrentCommandMap()<cr>
+
+  nmap <buffer> <silent> <C-K> []<C-J>]]
+
+  command! -bang -buffer CloseRepl
+    \ :call <SID>CloseRepl(bufnr(''), '<bang>' == '!')
+  command! -bang -buffer -nargs=1 -complete=file SaveInput
+    \ :call <SID>SaveInput(<f-args>, '<bang>' == '!')
+
+  "autocmd BufDelete,BufWipeout <buffer> :call CloseRepl(expand('<abuf>'))
+endfunction
+
+function! s:SaveInput(fname, force)
+  if filereadable(a:fname) " file exists
+    if !filewritable(a:fname)
+      echoerr 'File' a:fname 'is not writable'
+      return
+    elseif filewritable(a:fname) == 1 && !a:force
+      echoerr 'Use ! to overwrite' a:fname
+      return
+    endif
+  endif
+  let l:save = getpos('.')[1:2]
+  let l:prev = [1, 1]
+  call cursor(l:prev)
+  let l:text = []
+  while 1
+    let l:pos = s:StartOfNextPrompt(1)
+    if l:pos == l:prev || l:pos == [0, 0]
+      break
+    endif
+    let l:prev = l:pos
+    let l:lp = s:GetCurrentLinesAndPos()
+    if !empty(l:lp)
+      call add(l:text, join(l:lp.lines, b:replinfo.join))
+    endif
+  endwhile
+  call writefile(l:text, a:fname)
+  call cursor(l:save)
+endfunction
+
+" NAVIGATION
+function! s:EndOfCurrOrPrevPrompt(move)
+  let l:pos = getpos('.')[1:2]
+  let l:curr = s:EndOfCurrPrompt(a:move)
+  if l:curr[0] == l:pos[0] && l:curr[1] >= l:pos[1] " cursor is still in prompt area
+    " match only above current prompt
+    let l:pos = searchpos(b:replinfo.prompt.'\m\%<'.(l:curr[0]-1).'l\s*\zs',
+      \ (a:move ? '' : 'n').'bcW')
+  endif
+  return l:pos
+endfunction
+
+function! s:EndOfCurrPrompt(move)
+  let l:pos = match(getline('.'), b:replinfo.prompt.'\m\s*\zs')
+  if l:pos > -1
+    let l:result = [line('.'), l:pos + 1]
+    if a:move
+      call cursor(l:result[0], l:result[1])
+    endif
+    return l:result
+  endif
+  return searchpos(b:replinfo.prompt.'\m\s*\zs', (a:move ? '' : 'n').'bcW')
+endfunction
+
+function! s:StartOfNextPrompt(move)
+  return searchpos(b:replinfo.prompt, (a:move ? '' : 'n').'W')
+endfunction
+
+function! s:EndOfNextPrompt(move)
+  return searchpos(b:replinfo.prompt.'\m\s*\zs', (a:move ? '' : 'n').'W')
+endfunction
+
+function! s:GoToEndOfNextOrCurrentCommand()
+  let l:pos = searchpos('\m^'.b:replinfo.outmarker, 'nW')
+  if !l:pos[0]
+    let l:line = line('$')
+  else
+    let l:line = l:pos[0] - 1
+  endif
+  call cursor(l:line, len(getline(l:line)))
+endfunction
+
+function! s:GoToEndOfPrevCommand()
+  let l:curr = s:EndOfCurrPrompt(0)
+  " match only above current prompt
+  let l:pos = searchpos(b:replinfo.prompt.'\m\%<'.(l:curr[0]-1).'l\s*\zs', 'bcW')
+  if l:pos != [0, 0]
+    call s:GoToEndOfNextOrCurrentCommand()
+  endif
+endfunction
+
+function! s:StartOfNextPromptOrOutput(move)
+  let l:pos = searchpos('\m'.b:replinfo.prompt.'\m\|^'
+    \ .b:replinfo.outmarker, (a:move ? '' : 'n').'W')
+  return l:pos
+endfunction
+
+function! s:EndOfCurrOrPrevPromptMap()
+  for i in range(v:count1)
+    call s:EndOfCurrOrPrevPrompt(1)
+  endfor
+endfunction
+
+function! s:EndOfNextPromptMap()
+  for i in range(v:count1)
+    call s:EndOfNextPrompt(1)
+  endfor
+endfunction
+
+function! s:GoToEndOfPrevCommandMap()
+  for i in range(v:count1)
+    call s:GoToEndOfPrevCommand()
+  endfor
+endfunction
+
+function! s:GoToEndOfNextOrCurrentCommandMap()
+  for i in range(v:count1)
+    call s:GoToEndOfNextOrCurrentCommand()
+  endfor
+endfunction
+
+function! s:GetCurrentLinesAndPos()
+  if match(getline('.'), b:replinfo.prompt.'\m\s*$') > -1 " empty input line
+    return {}
+  endif
+  let l:start = s:EndOfCurrPrompt(1)
+  let l:end = s:StartOfNextPromptOrOutput(0)
+  if l:end == [0, 0]
+    let l:end = [line('$'), len(getline('$'))]
+  else
+    let l:end[0] -= 1
+  endif
+  let l:result = {'line1' : l:start[0], 'line2' : l:end[0], 'lines' : []}
+  if l:start != [0, 0]
+    let l:lines = getline(l:start[0], l:end[0])
+    let l:lines[0] = l:lines[0][l:start[1] - 1 : ] "column index is 1-based
+    let l:result.lines = l:lines
+  endif
+  return l:result
+endfunction
+
+function! s:Execute()
+  let l:current = s:GetCurrentLinesAndPos()
+  if empty(l:current)
+    return
+  endif
+  if !empty(l:current.lines)
+    let b:replinfo.curpos = l:current.line2
+    let l:next = s:StartOfNextPrompt(0)
+    if l:next != [0, 0]
+      " delete previous output
+      let l:from = l:current.line2 + 1
+      let l:to = l:next[0] - 2
+      exec 'silent' l:from ','  l:to 'delete _'
+    endif
+    call s:SendToRepl(join(l:current.lines, b:replinfo.join), 0, 0)
+  endif
+endfunction
+
+function! s:CopyCurrent()
+  let l:current = s:GetCurrentLinesAndPos()
+  if empty(l:current)
+    return
+  endif
+  let l:lines = l:current.lines
+  if l:current.line2 < line('$') && !empty(l:lines)
+    let l:lines[0] = getline('$') . l:lines[0]
+    call setline(line('$'), l:lines)
+    call cursor(line('$'), len(getline('$')))
+  endif
+endfunction
+
+let s:replbufs = {}
+
+function! s:IsBufferValid(buf)
+  if bufexists(a:buf)
+    let l:info = getbufvar(a:buf, 'replinfo')
+    return !empty(l:info) && l:info.proc.is_valid
+          \ && !l:info.proc.stdin.eof && !l:info.proc.stdout.eof
+  endif
+  return 0
+endfunction
+
+function! s:CleanupDeadBuffers()
+  for l:t in keys(s:replbufs)
+    call filter(s:replbufs[l:t], 's:IsBufferValid(v:val)')
+  endfor
+  call filter(s:replbufs, '!empty(v:val)')
+endfunction
+
+function! s:FindReplBuffer(type)
+  call s:CleanupDeadBuffers()
+  let l:b = 0
+  if exists('b:replbuf') && bufexists(b:replbuf)
+      \&& getbufvar(b:replbuf, 'replinfo').type == a:type
+    let l:b = b:replbuf
+  " check other buffers on the same tab first?
+  elseif exists('s:replbufs["'.a:type.'"]')
+    let l:b = s:replbufs[a:type][0]
+  endif
+  if l:b > 0 && bufwinnr(l:b) == -1 " window not visible
+    exec getbufvar(l:b, 'replinfo').split 'sbuffer'
+    wincmd W
+  endif
+  return l:b
+endfunction " FindReplBuffer
+
+function! s:NewReplBuffer(args, type)
+  call s:CleanupDeadBuffers()
+  " populate REPL info using default entry as a prototype
+  let l:replinfo = deepcopy(g:ReplDefaults)
+  call extend(l:replinfo, g:ReplTypes[a:type], 'force')
+  call extend(l:replinfo, {'curpos': 1, 'ready': 0, 'more': '', 'type': a:type})
+
+  try
+    let l:replinfo.proc = vimproc#popen2(l:replinfo.command . ' ' . a:args)
+  catch
+    echohl ErrorMsg | echomsg "Error creating process:" v:exception | echohl None
+    " rethrow?
+    return 0
+  endtry
+
+  exec l:replinfo.split 'new'
+  let b:replinfo = l:replinfo
+
+  call s:SendToRepl(b:replinfo.init, 0, 0)
+
+  let l:buf = bufnr('')
+  if exists('s:replbufs["'.a:type.'"]')
+    let l:bufs = s:replbufs[a:type]
+  else
+    let l:bufs = []
+  endif
+  call add(l:bufs, l:buf)
+  let s:replbufs[a:type] = l:bufs
+
+  call s:SetupBuffer()
+
+  wincmd W
+  return l:buf
+endfunction " NewReplBuffer
+
+function! s:CloseRepl(buffer, wipe)
+  let l:info = getbufvar(a:buffer, 'replinfo')
+  if l:info.proc.is_valid
+    call l:info.proc.kill(15)
+  endif
+  if a:wipe
+    exec a:buffer 'bwipe'
+  endif
+  call s:CleanupDeadBuffers()
+endfunction
+
+function! repl#OpenRepl(args, type, new)
+  call s:ReplInit2()
+  if a:new
+    let l:b = 0
+  else
+    let l:b = s:FindReplBuffer(a:type)
+  endif
+  if !l:b
+    let l:b = s:NewReplBuffer(a:args, a:type)
+  endif
+  if l:b > 0
+    let b:replbuf = l:b
+  endif
+endfunction " OpenRepl
+
+function! s:IsBufferWindowVisible(buf)
+  let l:src = bufwinnr('')
+  let l:win = bufwinnr(a:buf)
+  let l:result = 0
+  if l:win > -1
+    try
+      " check if we are able to switch to the buffer window and back
+      exec l:win 'wincmd w'
+      exec l:src 'wincmd w'
+      let l:result = 1
+    catch
+      let l:result = 0
+    endtry
+  endif
+  return l:result
+endfunction
+
+function! s:ReadFromRepl()
+  for l:t in keys(s:replbufs)
+    for l:b in s:replbufs[l:t]
+      if s:IsBufferValid(l:b) && s:IsBufferWindowVisible(l:b)
+        let l:info = getbufvar(l:b, 'replinfo')
+        let l:proc = l:info.proc
+        let l:text = l:proc.stdout.read()
+        call s:WriteToBuffer(l:b, l:text)
+      endif
+    endfor
+  endfor
+endfunction " ReadFromRepl
+
+function! s:WriteToBuffer(buf, text)
+  let l:src = bufwinnr('')
+  if !empty(a:text)
+    exec bufwinnr(a:buf) 'wincmd w'
+    let l:text = split(a:text, '\m[\r]\?\n', 1)
+    if b:replinfo.curpos < 1
+      let b:replinfo.curpos = line('$')
+    endif
+    if b:replinfo.ready
+      " new round of interaction
+      if !empty(b:replinfo.more)
+        call setline(b:replinfo.curpos, getline(b:replinfo.curpos) . b:replinfo.more)
+        let b:replinfo.more = ''
+      endif
+
+      let b:replinfo.ready = 0
+      call append(b:replinfo.curpos, b:replinfo.outmarker)
+      let b:replinfo.curpos += 1
+      call append(b:replinfo.curpos, l:text)
+      let b:replinfo.curpos += len(l:text)
+    else
+      let l:text[0] = getline(b:replinfo.curpos) . l:text[0]
+      call setline(b:replinfo.curpos, l:text)
+      let b:replinfo.curpos += len(l:text) - 1
+    endif
+    if b:replinfo.scroll
+      call cursor(b:replinfo.curpos, len(getline(b:replinfo.curpos)))
+    endif
+    if !b:replinfo.ready
+      let l:prompt = b:replinfo.prompt
+      if matchstr(l:text[-1], l:prompt) != ''
+            \ || matchstr(getline(line(b:replinfo.curpos)), l:prompt) != ''
+        " if the last output line is our prompt
+        let b:replinfo.ready = 1
+        " don't print prompt if the line is not the last one
+        if b:replinfo.curpos < line('$')
+          let l:from = b:replinfo.curpos - 1
+          let l:to = b:replinfo.curpos
+          exec 'silent' l:from ',' l:to 'delete _'
+          call s:EndOfCurrOrPrevPrompt(1) " return to the command
+          call s:GoToEndOfNextOrCurrentCommand()
+        endif
+      endif
+    endif
+    exec l:src 'wincmd w'
+  endif
+endfunction "WriteToBuffer
+
+function! s:SendToRepl(text, echo, append)
+  call s:CleanupDeadBuffers()
+  if empty(a:text)
+    return
+  endif
+  if exists('b:replinfo')
+    let l:b = bufnr('')
+  elseif exists('b:replbuf')
+    let l:b = b:replbuf
+  else " try to find some REPL buffer
+    let l:b = 0
+    for l:t in keys(s:replbufs)
+      for l:bf in s:replbufs[l:t]
+        if bufexists(l:bf)
+          let l:b = l:bf
+          break
+        endif
+      endfor
+      if l:b > 0
+        break
+      endif
+    endfor
+  endif
+  if !s:IsBufferValid(l:b)
+    echoerr 'REPL is not connected'
+    return
+  endif
+  let l:info = getbufvar(l:b, 'replinfo')
+  if type(a:text) == type('')
+    let l:text = a:text
+  elseif type(a:text) == type([])
+    let l:text = join(a:text, l:info.join)
+  else
+    let l:text = string(a:text)
+  endif
+  if a:echo
+    let l:info.more = l:text
+  endif
+  let l:proc = l:info.proc
+  if l:proc.is_valid && !l:proc.stdin.eof
+    if a:append
+      let l:info.curpos = -1
+    endif
+    return l:proc.stdin.write(l:text) + l:proc.stdin.write("\n")
+  endif
+endfunction " SendToRepl
+
+function! s:EvalSelection()
+  let l:lines = getline(line("'<"), line("'>"))
+  let l:lines[0] = l:lines[0][col("'<")-1 : ]
+  let l:lines[-1] = l:lines[-1][: col("'>")-1]
+  call s:SendToRepl(l:lines, 1, 1)
+endfunction " EvalSelection
+
+function! s:EvalLine()
+  call s:SendToRepl(getline('.'), 1, 1)
+endfunction " EvalLine
+
+" vim: set ts=8 sw=2 sts=2 et:
+" REPL plugin to interact with interpreters for various programming languages
+" Author: Sergey Khorev <sergey.khorev@gmail.com>
+" Last Change:	$HGLastChangedDate$
+"
+" Prerequisites: you need to install AND build Vimproc (https://github.com/Shougo/vimproc)
+"
+" Commands:
+" :Open<YourInterpreter> <ExtraArguments> - start session
+" e.g.
+"  :OpenGHCi to start GHCi 
+"  :OpenGHCi! to forcefully start a new session in a new window
+
+" :CloseRepl (local to the repl window) - disconnect REPL
+" :CloseRepl! - disconnect and wipeout the buffer
+" :SaveInput <filename> - save input lines, use ! to force overwrite
+"
+" Keybinding:
+" global:
+"  <Leader>e - in normal mode: send current line to the interpreter
+"            - in visual mode: send selection
+"
+" Local to the REPL window (NORMAL MODE ONLY!)
+"  <Return> - send current command to the interpreter
+"  <C-J> - copy current command to the command prompt
+"  <C-K> - recall previous command to the command prompt
+"  <count>[[ - navigate to the start of the current or previous command
+"  <count>]] - navigate to the start of the next command
+"  <count>[] - go to the end of the previous command
+"  <count>][ - go to the end of current or the next command
+"
+" Keybinding and syntax highlighting heavily use specific markers,
+"   you tamper with the markers on your own risk
+"
+" Hints:
+" You may edit and re-execute commands and the plugin should update output
+"   using markers
+" Also feel free to delete unneeded text, just try to keep the layout
+" Session transcript can be saved with "1,$w YourFileName"
+"
+" Customisation:
+" Define g:replUserDefaults and g:replUserTypes
+"   using g:ReplDefaults and g:ReplTypes as samples
+"   g:replUserDefaults provides default settings for all interpreters
+"   g:replUserTypes provides specific overrides
+" Feel free to send me settings for your favourite interpreter
+"
+" Fields:
+"   command - command used to start interpreter
+"   init    - commands to initialise the interpreter (e.g., set specific prompt)
+"   prompt  - regular expression to help REPL identify the prompt
+"   split   - split command to create REPL window
+"   outmarker - marker to designate start of interpreter output
+"   syntax  - Vim syntax highlighting for your interpreted language
+"   scroll  - move cursor in the REPL window when new data are received
+"   wrap    - not used for now
+"   join    - string used to concatenate multiple lines (many interpreters
+"               allow only one input line)
+
+if exists('g:loaded_repl')
+  finish
+endif
+
+let g:loaded_repl = 1
+
+if v:version < 703
+  echoerr "REPL: only Vim version 7.3 and newer is supported"
+  finish
+endif
+
+let g:ReplDefaults = 
+      \{'command' : '',
+      \ 'init'    : '',
+      \ 'prompt'  : '^[^>]*>',
+      \ 'split'   : 'belowright vertical',
+      \ 'outmarker': 'OUTPUT:',
+      \ 'syntax'  : '',
+      \ 'scroll'  : 1,
+      \ 'wrap'    : 0,
+      \ 'join'    : ' '}
+
+let g:ReplTypes =
+  \ {
+  \  'Bash':
+      \{'command' : 'bash -i',
+      \ 'init'    : "PS1='\nbash> '",
+      \ 'prompt'  : '\m\C^bash>',
+      \ 'syntax'  : 'sh'}
+  \, 'Chicken':
+      \{'command' : 'csi -:c',
+      \ 'init'    : '(repl-prompt (lambda () "\n\nchicken> "))',
+      \ 'prompt'  : '\m\C^chicken>',
+      \ 'syntax'  : 'scheme'}
+  \, 'Cmd':
+      \{'command' : 'cmd',
+      \ 'init'    : 'prompt cmd$G$S',
+      \ 'prompt'  : '\m\C^cmd>',
+      \ 'syntax'  : 'dosbatch'}
+  \, 'GHCi':
+      \{'command' : 'ghci',
+      \ 'init'    : ':set prompt "\nghci %s> "',
+      \ 'prompt'  : '\m\C^ghci [^>]\{-}>',
+      \ 'syntax'  : 'haskell'}
+  \, 'Hugs':
+      \{'command' : 'hugs -98 -p"\nhugs %s> "',
+      \ 'init'    : '',
+      \ 'prompt'  : '\m\C^hugs [^>]\{-}>',
+      \ 'syntax'  : 'haskell'}
+  \, 'Maxima':
+      \{'command' : 'maxima',
+      \ 'init'    : '',
+      \ 'prompt'  : '\m\C^(%i\d\+)',
+      \ 'syntax'  : 'maxima'}
+  \, 'Ocaml':
+      \{'command' : 'ocaml',
+      \ 'init'    : 'Toploop.read_interactive_input := let old = !Toploop.read_interactive_input in fun prompt buffer len -> old "\nocaml> " buffer len ;;',
+      \ 'prompt'  : '\m\C^ocaml>',
+      \ 'syntax'  : 'ocaml'}
+  \, 'Octave':
+      \{'command' : 'octave -i',
+      \ 'init'    : 'PS1("\noctave> ")',
+      \ 'prompt'  : '\m\C^octave>',
+      \ 'syntax'  : 'matlab'}
+  \, 'Python':
+      \{'command' : 'python -i',
+      \ 'init'    : "import sys\nsys.ps1=\"\\npython> \"",
+      \ 'prompt'  : '\m\C^python>',
+      \ 'split'   : 'belowright',
+      \ 'syntax'  : 'python'}
+  \, 'R':
+      \{'command' : 'R --no-save --ess',
+      \ 'init'    : 'options(prompt="\nR> ", continue="")',
+      \ 'prompt'  : '\m\C^R>',
+      \ 'syntax'  : 'r'}
+  \, 'Racket':
+      \{'command' : 'racket',
+      \ 'init'    : '(let ((c (current-prompt-read))) (current-prompt-read (lambda () (newline) (display "racket") (c))))',
+      \ 'prompt'  : '\m\C^racket> ',
+      \ 'syntax'  : 'scheme'}
+  \, 'Reduce':
+      \{'command' : 'reduce -w- -b',
+      \ 'init'    : '',
+      \ 'prompt'  : '\m\C^\d\+:',
+      \ 'syntax'  : ''}
+  \, 'Tcsh':
+      \{'command' : 'tcsh -i',
+      \ 'init'    : "set prompt=\"\\ntcsh> \"\nunset rprompt",
+      \ 'prompt'  : '\m\C^tcsh>',
+      \ 'syntax'  : 'tcsh'}
+  \ }
+
+" Not operational:
+"  How can we change nested prompt or disable nested at all?
+"  \, 'Guile':
+"      \{'command' : 'guile --',
+"      \ 'init'   : ',o prompt "\n\nguile> "',
+"      \        'prompt'  : '\m\C^guile>',
+"      \        'syntax'  : 'scheme'}
+"  Need to disable DWIM somehow, also what is the point of using REPL if facts
+"  need to be 'consult'ed anyway?
+"  \, 'SWIprolog':
+"      \{'command' : 'swipl -g "set_prolog_flag(color_term, false),set_stream(user_input, tty(true)),set_stream(user_output, tty(true))"',
+"      \ 'init'   : "'$set_prompt'('\nswipl> ').",
+"      \        'prompt'  : '\m\C^swipl>',
+"      \        'syntax'  : 'prolog'}
+"  gprolog - doesn't flush output
+"  erl - any use?
+
+function! s:ReplInit()
+  if exists('g:replUserDefaults')
+    call extend(g:replDefaults, g:replUserDefaults, 'force')
+  endif
+  if exists('g:replUserTypes')
+    call extend(g:replTypes, g:replUserTypes, 'force')
+  endif
+  for l:t in keys(g:ReplTypes)
+    exec 'command! -nargs=* -bang Open'.l:t.
+          \     ' call repl#OpenRepl(<q-args>, "'.l:t.'", "<bang>" == "!")'
+  endfor
+endfunction " ReplInit
+
+call s:ReplInit()
+delfunction s:ReplInit
+
+finish
+
+Vimball contents:
+plugin/repl.vim
+autoload/repl.vim
+syntax/repl.vim
+
+" vim: set ts=8 sw=2 sts=2 et:
+" `repl` plugin: syntax highlightling for REPL buffer
+" Author: Sergey Khorev <sergey.khorev@gmail.com>
+" Last Change:	$HGLastChangedDate$
+
+if exists('b:current_syntax')
+  finish
+endif
+
+if !empty(b:replinfo.syntax)
+  exec 'syn include @replNested syntax/'.b:replinfo.syntax.'.vim'
+  unlet b:current_syntax
+endif
+
+" folding?
+exec 'syn region replLine matchgroup=replPrompt start=!'.b:replinfo.prompt.
+  \'! end=!^'.b:replinfo.outmarker.'$\|'.b:replinfo.prompt.'$!me=s-1 contains=@replNested'
+exec 'syn match replOutputMarker !^'.b:replinfo.outmarker.'$!'
+
+hi def link replPrompt Question
+hi def link replOutputMarker Title
+
+let b:current_syntax = 'repl'
+
+" vim: set ts=8 sts=2 sw=2:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.