diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 320b154..3912ac1 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2662,14 +2662,15 @@ A jump table for the options with a short description can be found at |Q_op|.
 'endofline' 'eol'	boolean	(default on)
 			local to buffer
 			{not in Vi}
-	When writing a file and this option is off and the 'binary' option
-	is on, no <EOL> will be written for the last line in the file.  This
-	option is automatically set when starting to edit a new file, unless
-	the file does not have an <EOL> for the last line in the file, in
-	which case it is reset.  Normally you don't have to set or reset this
-	option.  When 'binary' is off the value is not used when writing the
-	file.  When 'binary' is on it is used to remember the presence of a
-	<EOL> for the last line in the file, so that when you write the file
+	When writing a file and this option is off and the 'binary' or
+	'respecteol' option is on, no <EOL> will be written for the last line
+	in the file.  This option is automatically set when starting to edit
+	a new file, unless the file does not have an <EOL> for the last line
+	in the file, in which case it is reset.  Normally you don't have to
+	set or reset this option.  When both 'binary' and 'respecteol' are off
+	the value is not used when writing the file.  When 'binary' or
+	'respecteol' is on it is used to remember the presence of a <EOL> for
+	the last line in the file, so that when you write the file
 	the situation from the original file can be kept.  But you can change
 	it if you want to.
 
@@ -5762,6 +5763,17 @@ A jump table for the options with a short description can be found at |Q_op|.
 	For the ":substitute" command the number of substitutions is used
 	instead of the number of lines.
 
+			*'respecteol'* *'reol'* *'norespecteol'* *'noreol'*
+'respecteol' 'reol'	boolean	(default off)
+			local to buffer
+			{not in Vi}
+	When writing a file and this option is on, the <EOL> for the last line
+	is only written if there was one in the original file (normally Vim
+	appends an <EOL> to the last line if there is none).
+	See the 'endofline' option.
+
+	Note: Same can be achived by setting the 'binary' option.
+
 			 *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'*
 'restorescreen' 'rs'	boolean	(default on)
 			global
diff --git a/runtime/doc/tags b/runtime/doc/tags
index 5524c42..52827d1 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -603,6 +603,8 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
 'noreadonly'	options.txt	/*'noreadonly'*
 'norelativenumber'	options.txt	/*'norelativenumber'*
 'noremap'	options.txt	/*'noremap'*
+'noreol'	options.txt	/*'noreol'*
+'norespecteol'	options.txt	/*'norespecteol'*
 'norestorescreen'	options.txt	/*'norestorescreen'*
 'norevins'	options.txt	/*'norevins'*
 'nori'	options.txt	/*'nori'*
@@ -759,7 +761,9 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
 'relativenumber'	options.txt	/*'relativenumber'*
 'remap'	options.txt	/*'remap'*
 'renderoptions'	options.txt	/*'renderoptions'*
+'reol'	options.txt	/*'reol'*
 'report'	options.txt	/*'report'*
+'respecteol'	options.txt	/*'respecteol'*
 'restorescreen'	options.txt	/*'restorescreen'*
 'revins'	options.txt	/*'revins'*
 'ri'	options.txt	/*'ri'*
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
