Skip to content

Commit ac22931

Browse files
committed
py/modsys: Add optional mutable attributes sys.ps1/ps2 and use them.
This allows customising the REPL prompt strings. Signed-off-by: Damien George <damien@micropython.org>
1 parent cac939d commit ac22931

File tree

15 files changed

+94
-12
lines changed

15 files changed

+94
-12
lines changed

docs/library/sys.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ Constants
132132
If you need to check whether your program runs on MicroPython (vs other
133133
Python implementation), use `sys.implementation` instead.
134134

135+
.. data:: ps1
136+
ps2
137+
138+
Mutable attributes holding strings, which are used for the REPL prompt. The defaults
139+
give the standard Python prompt of ``>>>`` and ``...``.
140+
135141
.. data:: stderr
136142

137143
Standard error `stream`.

ports/unix/main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ STATIC int do_repl(void) {
193193

194194
input_restart:
195195
vstr_reset(&line);
196-
int ret = readline(&line, ">>> ");
196+
int ret = readline(&line, mp_repl_get_ps1());
197197
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
198198

199199
if (ret == CHAR_CTRL_C) {
@@ -240,7 +240,7 @@ STATIC int do_repl(void) {
240240
// got a line with non-zero length, see if it needs continuing
241241
while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
242242
vstr_add_byte(&line, '\n');
243-
ret = readline(&line, "... ");
243+
ret = readline(&line, mp_repl_get_ps2());
244244
if (ret == CHAR_CTRL_C) {
245245
// cancel everything
246246
printf("\n");
@@ -265,13 +265,13 @@ STATIC int do_repl(void) {
265265
// use simple readline
266266

267267
for (;;) {
268-
char *line = prompt(">>> ");
268+
char *line = prompt((char *)mp_repl_get_ps1());
269269
if (line == NULL) {
270270
// EOF
271271
return 0;
272272
}
273273
while (mp_repl_continue_with_input(line)) {
274-
char *line2 = prompt("... ");
274+
char *line2 = prompt((char *)mp_repl_get_ps2());
275275
if (line2 == NULL) {
276276
break;
277277
}

ports/unix/variants/coverage/mpconfigvariant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#define MICROPY_PY_BUILTINS_HELP (1)
4646
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
4747
#define MICROPY_PY_SYS_GETSIZEOF (1)
48+
#define MICROPY_PY_SYS_PS1_PS2 (1)
4849
#define MICROPY_PY_SYS_TRACEBACKLIMIT (1)
4950
#define MICROPY_PY_MATH_CONSTANTS (1)
5051
#define MICROPY_PY_MATH_FACTORIAL (1)

py/modsys.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace);
185185

186186
#if MICROPY_PY_SYS_ATTR_DELEGATION
187187
STATIC const uint16_t sys_mutable_keys[] = {
188+
#if MICROPY_PY_SYS_PS1_PS2
189+
MP_QSTR_ps1,
190+
MP_QSTR_ps2,
191+
#endif
188192
#if MICROPY_PY_SYS_TRACEBACKLIMIT
189193
MP_QSTR_tracebacklimit,
190194
#endif

py/mpconfig.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,11 @@ typedef double mp_float_t;
13561356
#define MICROPY_PY_SYS_ATEXIT (0)
13571357
#endif
13581358

1359+
// Whether to provide sys.{ps1,ps2} mutable attributes, to control REPL prompts
1360+
#ifndef MICROPY_PY_SYS_PS1_PS2
1361+
#define MICROPY_PY_SYS_PS1_PS2 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES)
1362+
#endif
1363+
13591364
// Whether to provide "sys.settrace" function
13601365
#ifndef MICROPY_PY_SYS_SETTRACE
13611366
#define MICROPY_PY_SYS_SETTRACE (0)
@@ -1385,7 +1390,7 @@ typedef double mp_float_t;
13851390
// Whether the sys module supports attribute delegation
13861391
// This is enabled automatically when needed by other features
13871392
#ifndef MICROPY_PY_SYS_ATTR_DELEGATION
1388-
#define MICROPY_PY_SYS_ATTR_DELEGATION (MICROPY_PY_SYS_TRACEBACKLIMIT)
1393+
#define MICROPY_PY_SYS_ATTR_DELEGATION (MICROPY_PY_SYS_PS1_PS2 || MICROPY_PY_SYS_TRACEBACKLIMIT)
13891394
#endif
13901395

13911396
// Whether to provide "uerrno" module

py/mpstate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
// variable, but in the future it is hoped that the state can become local.
4242

4343
enum {
44+
#if MICROPY_PY_SYS_PS1_PS2
45+
MP_SYS_MUTABLE_PS1,
46+
MP_SYS_MUTABLE_PS2,
47+
#endif
4448
#if MICROPY_PY_SYS_TRACEBACKLIMIT
4549
MP_SYS_MUTABLE_TRACEBACKLIMIT,
4650
#endif

py/qstrdefs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ Q()
3939
Q(*)
4040
Q(_)
4141
Q(/)
42+
#if MICROPY_PY_SYS_PS1_PS2
43+
Q(>>> )
44+
Q(... )
45+
#endif
4246
#if MICROPY_PY_BUILTINS_STR_OP_MODULO
4347
Q(%#o)
4448
Q(%#x)

py/repl.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333

3434
#if MICROPY_HELPER_REPL
3535

36+
#if MICROPY_PY_SYS_PS1_PS2
37+
const char *mp_repl_get_psx(unsigned int entry) {
38+
if (mp_obj_is_str(MP_STATE_VM(sys_mutable)[entry])) {
39+
return mp_obj_str_get_str(MP_STATE_VM(sys_mutable)[entry]);
40+
} else {
41+
return "";
42+
}
43+
}
44+
#endif
45+
3646
STATIC bool str_startswith_word(const char *str, const char *head) {
3747
size_t i;
3848
for (i = 0; str[i] && head[i]; i++) {

py/repl.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,34 @@
3131
#include "py/mpprint.h"
3232

3333
#if MICROPY_HELPER_REPL
34+
35+
#if MICROPY_PY_SYS_PS1_PS2
36+
37+
const char *mp_repl_get_psx(unsigned int entry);
38+
39+
static inline const char *mp_repl_get_ps1(void) {
40+
return mp_repl_get_psx(MP_SYS_MUTABLE_PS1);
41+
}
42+
43+
static inline const char *mp_repl_get_ps2(void) {
44+
return mp_repl_get_psx(MP_SYS_MUTABLE_PS2);
45+
}
46+
47+
#else
48+
49+
static inline const char *mp_repl_get_ps1(void) {
50+
return ">>> ";
51+
}
52+
53+
static inline const char *mp_repl_get_ps2(void) {
54+
return "... ";
55+
}
56+
57+
#endif
58+
3459
bool mp_repl_continue_with_input(const char *input);
3560
size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print, const char **compl_str);
61+
3662
#endif
3763

3864
#endif // MICROPY_INCLUDED_PY_REPL_H

py/runtime.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ void mp_init(void) {
135135
MP_STATE_VM(sys_exitfunc) = mp_const_none;
136136
#endif
137137

138+
#if MICROPY_PY_SYS_PS1_PS2
139+
MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_PS1]) = MP_OBJ_NEW_QSTR(MP_QSTR__gt__gt__gt__space_);
140+
MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_PS2]) = MP_OBJ_NEW_QSTR(MP_QSTR__dot__dot__dot__space_);
141+
#endif
142+
138143
#if MICROPY_PY_SYS_SETTRACE
139144
MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL;
140145
MP_STATE_THREAD(prof_callback_is_executing) = false;

0 commit comments

Comments
 (0)