From 9f04dfb568b8af339ec34ea1a94fb2eb8890bf8c Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 21 Jan 2017 23:17:51 +1100 Subject: [PATCH] py: Add builtin help function to core, with default help msg. This builtin is configured using MICROPY_PY_BUILTINS_HELP, and is disabled by default. --- py/builtin.h | 4 +- py/builtinhelp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ py/modbuiltins.c | 3 ++ py/mpconfig.h | 11 ++++++ py/py.mk | 1 + 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 py/builtinhelp.c diff --git a/py/builtin.h b/py/builtin.h index 282eb1cc93..ec326d037b 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -53,6 +53,7 @@ MP_DECLARE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_globals_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hash_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hex_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_id_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj); @@ -72,7 +73,6 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj); // Defined by a port, but declared here for simplicity -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); @@ -118,4 +118,6 @@ extern const mp_obj_module_t mp_module_webrepl; extern const mp_obj_module_t mp_module_framebuf; extern const mp_obj_module_t mp_module_btree; +extern const char *MICROPY_PY_BUILTINS_HELP_TEXT; + #endif // __MICROPY_INCLUDED_PY_BUILTIN_H__ diff --git a/py/builtinhelp.c b/py/builtinhelp.c new file mode 100644 index 0000000000..768806bee0 --- /dev/null +++ b/py/builtinhelp.c @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/builtin.h" + +#if MICROPY_PY_BUILTINS_HELP + +const char *mp_help_default_text = +"Welcome to MicroPython!\n" +"\n" +"For online docs please visit http://docs.micropython.org/\n" +"\n" +"Control commands:\n" +" CTRL-A -- on a blank line, enter raw REPL mode\n" +" CTRL-B -- on a blank line, enter normal REPL mode\n" +" CTRL-C -- interrupt a running program\n" +" CTRL-D -- on a blank line, exit or do a soft reset\n" +" CTRL-E -- on a blank line, enter paste mode\n" +"\n" +"For further help on a specific object, type help(obj)\n" +; + +STATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) { + mp_print_str(MP_PYTHON_PRINTER, " "); + mp_obj_print(name_o, PRINT_STR); + mp_print_str(MP_PYTHON_PRINTER, " -- "); + mp_obj_print(value, PRINT_STR); + mp_print_str(MP_PYTHON_PRINTER, "\n"); +} + +STATIC void mp_help_print_obj(const mp_obj_t obj) { + // try to print something sensible about the given object + mp_print_str(MP_PYTHON_PRINTER, "object "); + mp_obj_print(obj, PRINT_STR); + mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj)); + + mp_map_t *map = NULL; + if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) { + map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj)); + } else { + mp_obj_type_t *type; + if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) { + type = obj; + } else { + type = mp_obj_get_type(obj); + } + if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) { + map = mp_obj_dict_get_map(type->locals_dict); + } + } + if (map != NULL) { + for (uint i = 0; i < map->alloc; i++) { + if (map->table[i].key != MP_OBJ_NULL) { + mp_help_print_info_about_object(map->table[i].key, map->table[i].value); + } + } + } +} + +STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // print a general help message + mp_print_str(MP_PYTHON_PRINTER, MICROPY_PY_BUILTINS_HELP_TEXT); + } else { + // try to print something sensible about the given object + mp_help_print_obj(args[0]); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, mp_builtin_help); + +#endif // MICROPY_PY_BUILTINS_HELP diff --git a/py/modbuiltins.c b/py/modbuiltins.c index b7c8ff2601..f62afd8074 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -666,6 +666,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_globals), MP_ROM_PTR(&mp_builtin_globals_obj) }, { MP_ROM_QSTR(MP_QSTR_hasattr), MP_ROM_PTR(&mp_builtin_hasattr_obj) }, { MP_ROM_QSTR(MP_QSTR_hash), MP_ROM_PTR(&mp_builtin_hash_obj) }, + #if MICROPY_PY_BUILTINS_HELP + { MP_ROM_QSTR(MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_builtin_hex_obj) }, { MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mp_builtin_id_obj) }, { MP_ROM_QSTR(MP_QSTR_isinstance), MP_ROM_PTR(&mp_builtin_isinstance_obj) }, diff --git a/py/mpconfig.h b/py/mpconfig.h index 6d18937177..70ad98daae 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -759,6 +759,17 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_MIN_MAX (1) #endif +// Whether to provide the help function +#ifndef MICROPY_PY_BUILTINS_HELP +#define MICROPY_PY_BUILTINS_HELP (0) +#endif + +// Use this to configure the help text shown for help(). It should be a +// variable with the type "const char*". A sensible default is provided. +#ifndef MICROPY_PY_BUILTINS_HELP_TEXT +#define MICROPY_PY_BUILTINS_HELP_TEXT mp_help_default_text +#endif + // Whether to set __file__ for imported modules #ifndef MICROPY_PY___FILE__ #define MICROPY_PY___FILE__ (1) diff --git a/py/py.mk b/py/py.mk index ec22fbe63a..b78cdba351 100644 --- a/py/py.mk +++ b/py/py.mk @@ -189,6 +189,7 @@ PY_O_BASENAME = \ binary.o \ builtinimport.o \ builtinevex.o \ + builtinhelp.o \ modarray.o \ modbuiltins.o \ modcollections.o \