diff --git a/src/fileio.c b/src/fileio.c
index 9965920..b7c7e22 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2623,9 +2623,9 @@ failed:
 #endif
 
     /*
-     * Trick: We remember if the last line of the read didn't have
-     * an eol even when 'binary' is off, for when writing it again with
-     * 'binary' on.  This is required for
+     * We remember if the last line of the read didn't have
+     * an eol even when 'binary' is off, for 'respecteol' support,
+     * or when writing it again with 'binary' on.  This is required for
      * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
      */
     curbuf->b_no_eol_lnum = read_no_eol_lnum;
@@ -4547,7 +4547,8 @@ restore_backup:
 	/* write failed or last line has no EOL: stop here */
 	if (end == 0
 		|| (lnum == end
-		    && write_bin
+		    && (write_bin
+			|| buf->b_p_reol)
 		    && (lnum == buf->b_no_eol_lnum
 			|| (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
 	{
diff --git a/src/memline.c b/src/memline.c
index e809360..3faedb9 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -5361,8 +5361,8 @@ ml_find_line_or_offset(buf, lnum, offp)
 	if (ffdos)
 	    size += lnum - 1;
 
-	/* Don't count the last line break if 'bin' and 'noeol'. */
-	if (buf->b_p_bin && !buf->b_p_eol)
+	/* Don't count the last line break if 'noeol' and 'bin' or 'reol'. */
+	if ((buf->b_p_reol || buf->b_p_bin) && !buf->b_p_eol)
 	    size -= ffdos + 1;
     }
 
diff --git a/src/netbeans.c b/src/netbeans.c
index 68ca301..98f9ca4 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -3802,7 +3802,7 @@ get_buf_size(buf_T *bufp)
 	    }
 	}
 	/* Correction for when last line doesn't have an EOL. */
-	if (!bufp->b_p_eol && bufp->b_p_bin)
+	if (!bufp->b_p_eol && (bufp->b_p_bin || bufp->b_p_reol))
 	    char_count -= eol_size;
     }
 
diff --git a/src/ops.c b/src/ops.c
index 32461a8..c8ecc3c 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -6910,7 +6910,8 @@ cursor_pos_info()
 					   &char_count_cursor, len, eol_size);
 		    if (lnum == curbuf->b_ml.ml_line_count
 			    && !curbuf->b_p_eol
-			    && curbuf->b_p_bin
+			    && (curbuf->b_p_bin
+				|| curbuf->b_p_reol)
 			    && (long)STRLEN(s) < len)
 			byte_count_cursor -= eol_size;
 		}
@@ -6934,7 +6935,7 @@ cursor_pos_info()
 	}
 
 	/* Correction for when last line doesn't have an EOL. */
-	if (!curbuf->b_p_eol && curbuf->b_p_bin)
+	if (!curbuf->b_p_eol && (curbuf->b_p_bin || curbuf->b_p_reol))
 	    byte_count -= eol_size;
 
 	if (VIsual_active)
diff --git a/src/option.c b/src/option.c
index a6ce0ac..507d751 100644
--- a/src/option.c
+++ b/src/option.c
@@ -98,6 +98,7 @@
 # define PV_INC		OPT_BOTH(OPT_BUF(BV_INC))
 #endif
 #define PV_EOL		OPT_BUF(BV_EOL)
+#define PV_REOL		OPT_BUF(BV_REOL)
 #define PV_EP		OPT_BOTH(OPT_BUF(BV_EP))
 #define PV_ET		OPT_BUF(BV_ET)
 #ifdef FEAT_MBYTE
@@ -306,6 +307,7 @@ static char_u	*p_cfu;
 static char_u	*p_ofu;
 #endif
 static int	p_eol;
+static int	p_reol;
 static int	p_et;
 #ifdef FEAT_MBYTE
 static char_u	*p_fenc;
@@ -2144,6 +2146,9 @@ static struct vimoption
     {"report",	    NULL,   P_NUM|P_VI_DEF,
 			    (char_u *)&p_report, PV_NONE,
 			    {(char_u *)2L, (char_u *)0L} SCRIPTID_INIT},
+    {"respecteol",  "reol", P_BOOL|P_VI_DEF|P_RSTAT,
+			    (char_u *)&p_reol, PV_REOL,
+			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
     {"restorescreen", "rs", P_BOOL|P_VI_DEF,
 #ifdef WIN3264
 			    (char_u *)&p_rs, PV_NONE,
@@ -7765,6 +7770,11 @@ set_bool_option(opt_idx, varp, value, opt_flags)
     {
 	redraw_titles();
     }
+    /* when 'respecteol' is changed, redraw the window title */
+    else if ((int *)varp == &curbuf->b_p_reol)
+    {
+	redraw_titles();
+    }
 # ifdef FEAT_MBYTE
     /* when 'bomb' is changed, redraw the window title and tab page text */
     else if ((int *)varp == &curbuf->b_p_bomb)
@@ -10160,6 +10170,7 @@ get_varp(p)
 	case PV_OFU:	return (char_u *)&(curbuf->b_p_ofu);
 #endif
 	case PV_EOL:	return (char_u *)&(curbuf->b_p_eol);
+	case PV_REOL:	return (char_u *)&(curbuf->b_p_reol);
 	case PV_ET:	return (char_u *)&(curbuf->b_p_et);
 #ifdef FEAT_MBYTE
 	case PV_FENC:	return (char_u *)&(curbuf->b_p_fenc);
@@ -11876,8 +11887,8 @@ save_file_ff(buf)
 /*
  * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value
  * from when editing started (save_file_ff() called).
- * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
- * changed and 'binary' is not set.
+ * Also when 'endofline' was changed and 'binary' or 'respecteol' is set,
+ * or when 'bomb' was changed and 'binary' is not set.
  * When "ignore_empty" is true don't consider a new, empty buffer to be
  * changed.
  */
@@ -11896,7 +11907,7 @@ file_ff_differs(buf, ignore_empty)
 	return FALSE;
     if (buf->b_start_ffc != *buf->b_p_ff)
 	return TRUE;
-    if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol)
+    if ((buf->b_p_bin || buf->b_p_reol) && buf->b_start_eol != buf->b_p_eol)
 	return TRUE;
 #ifdef FEAT_MBYTE
     if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb)
diff --git a/src/option.h b/src/option.h
index 7c7d35a..ac14c93 100644
--- a/src/option.h
+++ b/src/option.h
@@ -962,6 +962,7 @@ enum
     , BV_INC
 #endif
     , BV_EOL
+    , BV_REOL
     , BV_EP
     , BV_ET
     , BV_FENC
diff --git a/src/os_unix.c b/src/os_unix.c
index 57c013f..5182cf0 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4624,7 +4624,8 @@ mch_call_shell(cmd, options)
 				/* Finished a line, add a NL, unless this line
 				 * should not have one. */
 				if (lnum != curbuf->b_op_end.lnum
-					|| !curbuf->b_p_bin
+					|| (!curbuf->b_p_bin
+					    && !curbuf->b_p_reol)
 					|| (lnum != curbuf->b_no_eol_lnum
 					    && (lnum !=
 						    curbuf->b_ml.ml_line_count
diff --git a/src/os_win32.c b/src/os_win32.c
index b50ab95..7b494ca 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -4173,7 +4173,8 @@ sub_process_writer(LPVOID param)
 	    /* Finished a line, add a NL, unless this line should not have
 	     * one. */
 	    if (lnum != curbuf->b_op_end.lnum
-		|| !curbuf->b_p_bin
+		|| (!curbuf->b_p_bin
+		    && !curbuf->b_p_reol)
 		|| (lnum != curbuf->b_no_eol_lnum
 		    && (lnum != curbuf->b_ml.ml_line_count
 			|| curbuf->b_p_eol)))
diff --git a/src/structs.h b/src/structs.h
index fedd3b9..1ebdd0c 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1586,6 +1586,7 @@ struct file_buffer
     char_u	*b_p_ofu;	/* 'omnifunc' */
 #endif
     int		b_p_eol;	/* 'endofline' */
+    int		b_p_reol;	/* 'respecteol' */
     int		b_p_et;		/* 'expandtab' */
     int		b_p_et_nobin;	/* b_p_et saved for binary mode */
 #ifdef FEAT_MBYTE
diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
index d9385b2..59cc520 100644
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -59,7 +59,8 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
 		test_set.out \
 		test_signs.out \
 		test_textobjects.out \
-		test_utf8.out
+		test_utf8.out \
+		test_reol.out
 
 .SUFFIXES: .in .out
 
@@ -207,3 +208,4 @@ test_set.out: test_set.in
 test_signs.out: test_signs.in
 test_textobjects.out: test_textobjects.in
 test_utf8.out: test_utf8.in
+test_reol.out: test_reol.in
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
index 931784f..7709718 100644
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -58,7 +58,8 @@ SCRIPTS =	test3.out test4.out test5.out test6.out test7.out \
 		test_set.out \
 		test_signs.out \
 		test_textobjects.out \
-		test_utf8.out
+		test_utf8.out \
+		test_reol.out
 
 SCRIPTS32 =	test50.out test70.out
 
diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak
index fde59fe..1b2841f 100644
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -80,7 +80,8 @@ SCRIPTS =	test3.out test4.out test5.out test6.out test7.out \
 		test_set.out \
 		test_signs.out \
 		test_textobjects.out \
-		test_utf8.out
+		test_utf8.out \
+		test_reol.out
 
 SCRIPTS32 =	test50.out test70.out
 
diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
index 5a59cf5..a4aff63 100644
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -60,7 +60,8 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
 		test_set.out \
 		test_signs.out \
 		test_textobjects.out \
-		test_utf8.out
+		test_utf8.out \
+		test_reol.out
 
 SCRIPTS_BENCH = bench_re_freeze.out
 
diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
index 427954e..205e484 100644
--- a/src/testdir/Make_vms.mms
+++ b/src/testdir/Make_vms.mms
@@ -119,7 +119,8 @@ SCRIPT = test1.out  test2.out  test3.out  test4.out  test5.out  \
 	 test_set.out \
 	 test_signs.out \
 	 test_textobjects.out \
-	 test_utf8.out
+	 test_utf8.out \
+	 test_reol.out
 
 # Known problems:
 # test17: ?
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index 420ed6a..e2a6a7a 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -56,7 +56,8 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
 		test_set.out \
 		test_signs.out \
 		test_textobjects.out \
-		test_utf8.out
+		test_utf8.out \
+		test_reol.out
 
 SCRIPTS_GUI = test16.out
 
diff --git a/src/testdir/test_reol.in b/src/testdir/test_reol.in
new file mode 100644
index 0000000..e29b78a
--- /dev/null
+++ b/src/testdir/test_reol.in
@@ -0,0 +1,40 @@
+Tests for 'respecteol'                         vim: set ft=vim :
+ 
+STARTTEST
+:" first write two test files – with and without trailing EOL
+:" use Unix fileformat for consistency
+:set ff=unix
+:enew!
+awith eol:w! XXEol
+:enew!
+:set reol noeol
+awithout eol:w! XXNoEol
+:set noreol eol
+:bwipe XXEol XXNoEol
+:"
+:" try editing files with 'respecteol' enabled
+:e! XXEol
+ostays eol:set reol
+:w! XXTestEol
+:e! XXNoEol
+ostays without:set reol
+:w! XXTestNoEol
+:bwipe XXEol XXNoEol XXTestEol XXTestNoEol
+:set noreol
+:"
+:" Append "END" to each file so that we can see what the last written char was.
+ggdGaEND:w >>XXEol
+:w >>XXNoEol
+:w >>XXTestEol
+:w >>XXTestNoEol
+:"
+:" Concatenate the results
+:e! test.out
+a0:$r XXEol
+:$r XXNoEol
+Go1:$r XXTestEol
+:$r XXTestNoEol
+:w
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test_reol.ok b/src/testdir/test_reol.ok
new file mode 100644
index 0000000..68ac9be
--- /dev/null
+++ b/src/testdir/test_reol.ok
@@ -0,0 +1,10 @@
+0
+with eol
+END
+without eolEND
+1
+with eol
+stays eol
+END
+without eol
+stays withoutEND
