2017-01-21 07:17:51 -05:00
/*
* 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 <stdio.h>
2017-01-21 20:12:54 -05:00
# include <string.h>
2017-01-21 07:17:51 -05:00
2018-11-09 19:41:08 -05:00
# include "genhdr/mpversion.h"
2017-01-21 07:17:51 -05:00
# include "py/builtin.h"
2017-06-20 13:56:05 -04:00
# include "py/mpconfig.h"
2017-01-21 20:12:54 -05:00
# include "py/objmodule.h"
2017-01-21 07:17:51 -05:00
# if MICROPY_PY_BUILTINS_HELP
2017-09-12 02:03:52 -04:00
const char mp_help_default_text [ ] =
2017-01-21 07:17:51 -05:00
" 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 " ) ;
}
2017-01-21 20:12:54 -05:00
# if MICROPY_PY_BUILTINS_HELP_MODULES
STATIC void mp_help_add_from_map ( mp_obj_t list , const mp_map_t * map ) {
for ( size_t i = 0 ; i < map - > alloc ; i + + ) {
if ( MP_MAP_SLOT_IS_FILLED ( map , i ) ) {
mp_obj_list_append ( list , map - > table [ i ] . key ) ;
}
}
}
# if MICROPY_MODULE_FROZEN
STATIC void mp_help_add_from_names ( mp_obj_t list , const char * name ) {
while ( * name ) {
size_t l = strlen ( name ) ;
// name should end in '.py' and we strip it off
2017-11-15 21:17:51 -05:00
mp_obj_list_append ( list , mp_obj_new_str ( name , l - 3 ) ) ;
2017-01-21 20:12:54 -05:00
name + = l + 1 ;
}
}
# endif
2017-07-15 17:03:24 -04:00
// These externs were originally declared inside mp_help_print_modules(),
// but they triggered -Wnested-externs, so they were moved outside.
# if MICROPY_MODULE_FROZEN_STR
extern const char mp_frozen_str_names [ ] ;
# endif
# if MICROPY_MODULE_FROZEN_MPY
extern const char mp_frozen_mpy_names [ ] ;
# endif
2017-01-21 20:12:54 -05:00
STATIC void mp_help_print_modules ( void ) {
mp_obj_t list = mp_obj_new_list ( 0 , NULL ) ;
mp_help_add_from_map ( list , & mp_builtin_module_map ) ;
# if MICROPY_MODULE_WEAK_LINKS
mp_help_add_from_map ( list , & mp_builtin_module_weak_links_map ) ;
# endif
# if MICROPY_MODULE_FROZEN_STR
mp_help_add_from_names ( list , mp_frozen_str_names ) ;
# endif
# if MICROPY_MODULE_FROZEN_MPY
mp_help_add_from_names ( list , mp_frozen_mpy_names ) ;
# endif
// sort the list so it's printed in alphabetical order
mp_obj_list_sort ( 1 , & list , ( mp_map_t * ) & mp_const_empty_map ) ;
// print the list of modules in a column-first order
# define NUM_COLUMNS (4)
# define COLUMN_WIDTH (18)
2018-05-02 02:50:28 -04:00
size_t len ;
2017-01-21 20:12:54 -05:00
mp_obj_t * items ;
mp_obj_list_get ( list , & len , & items ) ;
unsigned int num_rows = ( len + NUM_COLUMNS - 1 ) / NUM_COLUMNS ;
for ( unsigned int i = 0 ; i < num_rows ; + + i ) {
unsigned int j = i ;
for ( ; ; ) {
int l = mp_print_str ( MP_PYTHON_PRINTER , mp_obj_str_get_str ( items [ j ] ) ) ;
j + = num_rows ;
if ( j > = len ) {
break ;
}
int gap = COLUMN_WIDTH - l ;
while ( gap < 1 ) {
gap + = COLUMN_WIDTH ;
}
while ( gap - - ) {
mp_print_str ( MP_PYTHON_PRINTER , " " ) ;
}
}
mp_print_str ( MP_PYTHON_PRINTER , " \n " ) ;
}
// let the user know there may be other modules available from the filesystem
2018-11-09 19:41:08 -05:00
const compressed_string_t * compressed = translate ( " Plus any modules on the filesystem \n " ) ;
2020-05-28 08:40:56 -04:00
char decompressed [ decompress_length ( compressed ) ] ;
2018-11-09 19:41:08 -05:00
decompress ( compressed , decompressed ) ;
mp_print_str ( MP_PYTHON_PRINTER , decompressed ) ;
2017-01-21 20:12:54 -05:00
}
# endif
2017-01-21 07:17:51 -05:00
STATIC void mp_help_print_obj ( const mp_obj_t obj ) {
2017-01-21 20:12:54 -05:00
# if MICROPY_PY_BUILTINS_HELP_MODULES
if ( obj = = MP_OBJ_NEW_QSTR ( MP_QSTR_modules ) ) {
mp_help_print_modules ( ) ;
return ;
}
# endif
2017-09-10 01:15:41 -04:00
mp_obj_type_t * type = mp_obj_get_type ( obj ) ;
2017-01-21 07:17:51 -05:00
// try to print something sensible about the given object
mp_print_str ( MP_PYTHON_PRINTER , " object " ) ;
mp_obj_print ( obj , PRINT_STR ) ;
2017-09-10 01:15:41 -04:00
mp_printf ( MP_PYTHON_PRINTER , " is of type %q \n " , type - > name ) ;
2017-01-21 07:17:51 -05:00
mp_map_t * map = NULL ;
2017-09-10 01:15:41 -04:00
if ( type = = & mp_type_module ) {
2017-01-21 07:17:51 -05:00
map = mp_obj_dict_get_map ( mp_obj_module_get_globals ( obj ) ) ;
} else {
2017-09-10 01:15:41 -04:00
if ( type = = & mp_type_type ) {
type = MP_OBJ_TO_PTR ( obj ) ;
2017-01-21 07:17:51 -05:00
}
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 ) {
2018-11-09 19:41:08 -05:00
// print a general help message. Translate only works on single strings on one line.
const compressed_string_t * compressed =
translate ( " Welcome to Adafruit CircuitPython %s! \n \n Please visit learn.adafruit.com/category/circuitpython for project guides. \n \n To list built-in modules please do `help( \" modules \" )`. \n " ) ;
2020-05-28 08:40:56 -04:00
char decompressed [ decompress_length ( compressed ) ] ;
2018-11-09 19:41:08 -05:00
decompress ( compressed , decompressed ) ;
mp_printf ( MP_PYTHON_PRINTER , decompressed , MICROPY_GIT_TAG ) ;
2017-01-21 07:17:51 -05:00
} 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