diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c
index 8909c8be6de3ef90a5967414566cb71803526675..d0449e97ea9295322dc6cd87aec4c302de1a7497 100644
--- a/lib/mp-readline/readline.c
+++ b/lib/mp-readline/readline.c
@@ -160,9 +160,29 @@ int readline_process_char(int c) {
         } else if (c == 8 || c == 127) {
             // backspace/delete
             if (rl.cursor_pos > rl.orig_line_len) {
-                vstr_cut_out_bytes(rl.line, rl.cursor_pos - 1, 1);
+                // work out how many chars to backspace
+                #if MICROPY_REPL_AUTO_INDENT
+                int nspace = 0;
+                for (size_t i = rl.orig_line_len; i < rl.cursor_pos; i++) {
+                    if (rl.line->buf[i] != ' ') {
+                        nspace = 0;
+                        break;
+                    }
+                    nspace += 1;
+                }
+                if (nspace < 4) {
+                    nspace = 1;
+                } else {
+                    nspace = 4;
+                }
+                #else
+                int nspace = 1;
+                #endif
+
+                // do the backspace
+                vstr_cut_out_bytes(rl.line, rl.cursor_pos - nspace, nspace);
                 // set redraw parameters
-                redraw_step_back = 1;
+                redraw_step_back = nspace;
                 redraw_from_cursor = true;
             }
         #if MICROPY_HELPER_REPL
@@ -335,11 +355,44 @@ delete_key:
     return -1;
 }
 
+#if MICROPY_REPL_AUTO_INDENT
+STATIC void readline_auto_indent(void) {
+    vstr_t *line = rl.line;
+    if (line->len > 1 && line->buf[line->len - 1] == '\n') {
+        int i;
+        for (i = line->len - 1; i > 0; i--) {
+            if (line->buf[i - 1] == '\n') {
+                break;
+            }
+        }
+        size_t j;
+        for (j = i; j < line->len; j++) {
+            if (line->buf[j] != ' ') {
+                break;
+            }
+        }
+        // i=start of line; j=first non-space
+        int n = (j - i) / 4;
+        if (line->buf[line->len - 2] == ':') {
+            n += 1;
+        }
+        while (n-- > 0) {
+            vstr_add_strn(line, "    ", 4);
+            mp_hal_stdout_tx_strn("    ", 4);
+            rl.cursor_pos += 4;
+        }
+    }
+}
+#endif
+
 void readline_note_newline(const char *prompt) {
     rl.orig_line_len = rl.line->len;
     rl.cursor_pos = rl.orig_line_len;
     rl.prompt = prompt;
     mp_hal_stdout_tx_str(prompt);
+    #if MICROPY_REPL_AUTO_INDENT
+    readline_auto_indent();
+    #endif
 }
 
 void readline_init(vstr_t *line, const char *prompt) {
@@ -351,6 +404,9 @@ void readline_init(vstr_t *line, const char *prompt) {
     rl.cursor_pos = rl.orig_line_len;
     rl.prompt = prompt;
     mp_hal_stdout_tx_str(prompt);
+    #if MICROPY_REPL_AUTO_INDENT
+    readline_auto_indent();
+    #endif
 }
 
 int readline(vstr_t *line, const char *prompt) {
diff --git a/py/mpconfig.h b/py/mpconfig.h
index ce6fa6ceaee74c869e0a24102b103630ab6bb7bc..eb5b7243feafc0a70c341fe7eb6b276e8fda6481 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -302,6 +302,11 @@
 #define MICROPY_REPL_EMACS_KEYS (0)
 #endif
 
+// Whether to implement auto-indent in REPL
+#ifndef MICROPY_REPL_AUTO_INDENT
+#define MICROPY_REPL_AUTO_INDENT (0)
+#endif
+
 // Whether port requires event-driven REPL functions
 #ifndef MICROPY_REPL_EVENT_DRIVEN
 #define MICROPY_REPL_EVENT_DRIVEN (0)