builtinhelp.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013-2016 Damien P. George
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include "py/builtin.h"
  29. #include "py/objmodule.h"
  30. #if MICROPY_PY_BUILTINS_HELP
  31. const char mp_help_default_text[] =
  32. "Welcome to MicroPython!\n"
  33. "\n"
  34. "For online docs please visit http://docs.micropython.org/\n"
  35. "\n"
  36. "Control commands:\n"
  37. " CTRL-A -- on a blank line, enter raw REPL mode\n"
  38. " CTRL-B -- on a blank line, enter normal REPL mode\n"
  39. " CTRL-C -- interrupt a running program\n"
  40. " CTRL-D -- on a blank line, exit or do a soft reset\n"
  41. " CTRL-E -- on a blank line, enter paste mode\n"
  42. "\n"
  43. "For further help on a specific object, type help(obj)\n"
  44. ;
  45. STATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
  46. mp_print_str(MP_PYTHON_PRINTER, " ");
  47. mp_obj_print(name_o, PRINT_STR);
  48. mp_print_str(MP_PYTHON_PRINTER, " -- ");
  49. mp_obj_print(value, PRINT_STR);
  50. mp_print_str(MP_PYTHON_PRINTER, "\n");
  51. }
  52. #if MICROPY_PY_BUILTINS_HELP_MODULES
  53. STATIC void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) {
  54. for (size_t i = 0; i < map->alloc; i++) {
  55. if (MP_MAP_SLOT_IS_FILLED(map, i)) {
  56. mp_obj_list_append(list, map->table[i].key);
  57. }
  58. }
  59. }
  60. #if MICROPY_MODULE_FROZEN
  61. STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) {
  62. while (*name) {
  63. size_t l = strlen(name);
  64. // name should end in '.py' and we strip it off
  65. mp_obj_list_append(list, mp_obj_new_str(name, l - 3));
  66. name += l + 1;
  67. }
  68. }
  69. #endif
  70. STATIC void mp_help_print_modules(void) {
  71. mp_obj_t list = mp_obj_new_list(0, NULL);
  72. mp_help_add_from_map(list, &mp_builtin_module_map);
  73. #if MICROPY_MODULE_WEAK_LINKS
  74. mp_help_add_from_map(list, &mp_builtin_module_weak_links_map);
  75. #endif
  76. #if MICROPY_MODULE_FROZEN_STR
  77. extern const char mp_frozen_str_names[];
  78. mp_help_add_from_names(list, mp_frozen_str_names);
  79. #endif
  80. #if MICROPY_MODULE_FROZEN_MPY
  81. extern const char mp_frozen_mpy_names[];
  82. mp_help_add_from_names(list, mp_frozen_mpy_names);
  83. #endif
  84. // sort the list so it's printed in alphabetical order
  85. mp_obj_list_sort(1, &list, (mp_map_t*)&mp_const_empty_map);
  86. // print the list of modules in a column-first order
  87. #define NUM_COLUMNS (4)
  88. #define COLUMN_WIDTH (18)
  89. size_t len;
  90. mp_obj_t *items;
  91. mp_obj_list_get(list, &len, &items);
  92. unsigned int num_rows = (len + NUM_COLUMNS - 1) / NUM_COLUMNS;
  93. for (unsigned int i = 0; i < num_rows; ++i) {
  94. unsigned int j = i;
  95. for (;;) {
  96. int l = mp_print_str(MP_PYTHON_PRINTER, mp_obj_str_get_str(items[j]));
  97. j += num_rows;
  98. if (j >= len) {
  99. break;
  100. }
  101. int gap = COLUMN_WIDTH - l;
  102. while (gap < 1) {
  103. gap += COLUMN_WIDTH;
  104. }
  105. while (gap--) {
  106. mp_print_str(MP_PYTHON_PRINTER, " ");
  107. }
  108. }
  109. mp_print_str(MP_PYTHON_PRINTER, "\n");
  110. }
  111. // let the user know there may be other modules available from the filesystem
  112. mp_print_str(MP_PYTHON_PRINTER, "Plus any modules on the filesystem\n");
  113. }
  114. #endif
  115. STATIC void mp_help_print_obj(const mp_obj_t obj) {
  116. #if MICROPY_PY_BUILTINS_HELP_MODULES
  117. if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) {
  118. mp_help_print_modules();
  119. return;
  120. }
  121. #endif
  122. mp_obj_type_t *type = mp_obj_get_type(obj);
  123. // try to print something sensible about the given object
  124. mp_print_str(MP_PYTHON_PRINTER, "object ");
  125. mp_obj_print(obj, PRINT_STR);
  126. mp_printf(MP_PYTHON_PRINTER, " is of type %q\n", type->name);
  127. mp_map_t *map = NULL;
  128. if (type == &mp_type_module) {
  129. map = &mp_obj_module_get_globals(obj)->map;
  130. } else {
  131. if (type == &mp_type_type) {
  132. type = MP_OBJ_TO_PTR(obj);
  133. }
  134. if (type->locals_dict != NULL) {
  135. map = &type->locals_dict->map;
  136. }
  137. }
  138. if (map != NULL) {
  139. for (uint i = 0; i < map->alloc; i++) {
  140. if (map->table[i].key != MP_OBJ_NULL) {
  141. mp_help_print_info_about_object(map->table[i].key, map->table[i].value);
  142. }
  143. }
  144. }
  145. }
  146. STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) {
  147. if (n_args == 0) {
  148. // print a general help message
  149. mp_print_str(MP_PYTHON_PRINTER, MICROPY_PY_BUILTINS_HELP_TEXT);
  150. } else {
  151. // try to print something sensible about the given object
  152. mp_help_print_obj(args[0]);
  153. }
  154. return mp_const_none;
  155. }
  156. MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, mp_builtin_help);
  157. #endif // MICROPY_PY_BUILTINS_HELP