patch 8.1.0027: difficult to make a plugin that feeds a line to a job

Problem:    Difficult to make a plugin that feeds a line to a job.
Solution:   Add the nitial code for the "prompt" buftype.
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index e36089a..6a0126b 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -147,6 +147,7 @@
 	    test_perl.res \
 	    test_plus_arg_edit.res \
 	    test_preview.res \
+	    test_prompt_buffer.res \
 	    test_profile.res \
 	    test_python2.res \
 	    test_python3.res \
diff --git a/src/testdir/screendump.vim b/src/testdir/screendump.vim
index 3c424a0..80d51c3 100644
--- a/src/testdir/screendump.vim
+++ b/src/testdir/screendump.vim
@@ -5,19 +5,18 @@
   finish
 endif
 
-" Need to be able to run terminal Vim with 256 colors.  On MS-Windows the
-" console only has 16 colors and the GUI can't run in a terminal.
-if !has('terminal') || has('win32')
-  func CanRunVimInTerminal()
-    return 0
-  endfunc
+" For most tests we need to be able to run terminal Vim with 256 colors.  On
+" MS-Windows the console only has 16 colors and the GUI can't run in a
+" terminal.
+func CanRunVimInTerminal()
+  return has('terminal') && !has('win32')
+endfunc
+
+" Skip the rest if there is no terminal feature at all.
+if !has('terminal')
   finish
 endif
 
-func CanRunVimInTerminal()
-  return 1
-endfunc
-
 source shared.vim
 
 " Run Vim with "arguments" in a new terminal window.
@@ -54,6 +53,7 @@
   let cols = get(a:options, 'cols', 75)
 
   let cmd = GetVimCommandClean()
+
   " Add -v to have gvim run in the terminal (if possible)
   let cmd .= ' -v ' . a:arguments
   let buf = term_start(cmd, {'curwin': 1, 'term_rows': rows, 'term_cols': cols})
@@ -64,11 +64,12 @@
     let cols = term_getsize(buf)[1]
   endif
 
-  " Wait for "All" or "Top" of the ruler in the status line to be shown.  This
-  " can be quite slow (e.g. when using valgrind).
+  " Wait for "All" or "Top" of the ruler to be shown in the last line or in
+  " the status line of the last window. This can be quite slow (e.g. when
+  " using valgrind).
   " If it fails then show the terminal contents for debugging.
   try
-    call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1})
+    call WaitFor({-> len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - 1)) >= cols - 1})
   catch /timed out after/
     let lines = map(range(1, rows), {key, val -> term_getline(buf, val)})
     call assert_report('RunVimInTerminal() failed, screen contents: ' . join(lines, "<NL>"))
@@ -80,7 +81,7 @@
 " Stop a Vim running in terminal buffer "buf".
 func StopVimInTerminal(buf)
   call assert_equal("running", term_getstatus(a:buf))
-  call term_sendkeys(a:buf, "\<Esc>\<Esc>:qa!\<cr>")
+  call term_sendkeys(a:buf, "\<Esc>:qa!\<cr>")
   call WaitForAssert({-> assert_equal("finished", term_getstatus(a:buf))})
   only!
 endfunc
diff --git a/src/testdir/test_prompt_buffer.vim b/src/testdir/test_prompt_buffer.vim
new file mode 100644
index 0000000..a21acc7
--- /dev/null
+++ b/src/testdir/test_prompt_buffer.vim
@@ -0,0 +1,55 @@
+" Tests for setting 'buftype' to "prompt"
+
+if !has('channel')
+  finish
+endif
+
+source shared.vim
+source screendump.vim
+
+func Test_prompt_basic()
+  " We need to use a terminal window to be able to feed keys without leaving
+  " Insert mode.
+  if !has('terminal')
+    call assert_report('no terminal')
+    return
+  endif
+  call writefile([
+	\ 'func TextEntered(text)',
+	\ '  if a:text == "exit"',
+	\ '    stopinsert',
+	\ '    close',
+	\ '  else',
+	\ '    " Add the output above the current prompt.',
+	\ '    call append(line("$") - 1, "Command: \"" . a:text . "\"")',
+	\ '    " Reset &modified to allow the buffer to be closed.',
+	\ '    set nomodified',
+	\ '    call timer_start(20, {id -> TimerFunc(a:text)})',
+	\ '  endif',
+	\ 'endfunc',
+	\ '',
+	\ 'func TimerFunc(text)',
+	\ '  " Add the output above the current prompt.',
+	\ '  call append(line("$") - 1, "Result: \"" . a:text . "\"")',
+	\ 'endfunc',
+	\ '',
+	\ 'call setline(1, "other buffer")',
+	\ 'new',
+	\ 'set buftype=prompt',
+	\ 'call prompt_setcallback(bufnr(""), function("TextEntered"))',
+	\ 'startinsert',
+	\ ], 'Xpromptscript')
+  let buf = RunVimInTerminal('-S Xpromptscript', {})
+  call WaitForAssert({-> assert_equal('%', term_getline(buf, 1))})
+
+  call term_sendkeys(buf, "hello\<CR>")
+  call WaitForAssert({-> assert_equal('% hello', term_getline(buf, 1))})
+  call WaitForAssert({-> assert_equal('Command: "hello"', term_getline(buf, 2))})
+  call WaitForAssert({-> assert_equal('Result: "hello"', term_getline(buf, 3))})
+
+  call term_sendkeys(buf, "exit\<CR>")
+  call WaitForAssert({-> assert_equal('other buffer', term_getline(buf, 1))})
+
+  call StopVimInTerminal(buf)
+  call delete('Xpromptscript')
+endfunc