snappy 3.0.3__cp38-cp38-macosx_11_0_arm64.whl → 3.2__cp38-cp38-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- snappy/CyOpenGL.cpython-38-darwin.so +0 -0
- snappy/SnapPy.cpython-38-darwin.so +0 -0
- snappy/SnapPyHP.cpython-38-darwin.so +0 -0
- snappy/__init__.py +373 -426
- snappy/app.py +240 -75
- snappy/app_menus.py +93 -78
- snappy/browser.py +87 -63
- snappy/cache.py +5 -8
- snappy/canonical.py +249 -0
- snappy/{verify/cusp_shapes.py → cusps/__init__.py} +11 -19
- snappy/cusps/cusp_area_matrix.py +101 -0
- snappy/{verify/cusp_areas.py → cusps/cusp_areas_from_matrix.py} +39 -54
- snappy/cusps/maximal_cusp_area_matrix.py +136 -0
- snappy/cusps/test.py +21 -0
- snappy/cusps/trig_cusp_area_matrix.py +63 -0
- snappy/database.py +40 -31
- snappy/db_utilities.py +13 -14
- snappy/decorated_isosig.py +377 -133
- snappy/dev/extended_ptolemy/complexVolumesClosed.py +42 -9
- snappy/dev/extended_ptolemy/extended.py +32 -25
- snappy/dev/extended_ptolemy/giac_rur.py +23 -8
- snappy/dev/extended_ptolemy/phc_wrapper.py +10 -10
- snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +2 -1
- snappy/dev/vericlosed/gimbalLoopFinder.py +5 -5
- snappy/dev/vericlosed/hyperbolicStructure.py +3 -3
- snappy/dev/vericlosed/oneVertexTruncatedComplex.py +2 -2
- snappy/dev/vericlosed/truncatedComplex.py +3 -2
- snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +4 -3
- snappy/doc/_images/geodesics.jpg +0 -0
- snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
- snappy/doc/_images/m125_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
- snappy/doc/_sources/additional_classes.rst.txt +1 -0
- snappy/doc/_sources/credits.rst.txt +6 -1
- snappy/doc/_sources/development.rst.txt +69 -50
- snappy/doc/_sources/index.rst.txt +101 -66
- snappy/doc/_sources/installing.rst.txt +148 -165
- snappy/doc/_sources/news.rst.txt +136 -32
- snappy/doc/_sources/ptolemy.rst.txt +1 -1
- snappy/doc/_sources/ptolemy_examples1.rst.txt +9 -8
- snappy/doc/_sources/ptolemy_examples2.rst.txt +3 -3
- snappy/doc/_sources/ptolemy_examples3.rst.txt +14 -14
- snappy/doc/_sources/ptolemy_prelim.rst.txt +1 -1
- snappy/doc/_sources/snap.rst.txt +2 -2
- snappy/doc/_sources/snappy.rst.txt +1 -1
- snappy/doc/_sources/triangulation.rst.txt +3 -2
- snappy/doc/_sources/verify.rst.txt +89 -29
- snappy/doc/_sources/verify_internals.rst.txt +5 -16
- snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
- snappy/doc/_static/SnapPy.ico +0 -0
- snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
- snappy/doc/_static/basic.css +47 -27
- snappy/doc/_static/css/badge_only.css +1 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
- snappy/doc/_static/css/theme.css +4 -0
- snappy/doc/_static/doctools.js +107 -274
- snappy/doc/_static/documentation_options.js +6 -5
- snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- snappy/doc/_static/jquery.js +2 -2
- snappy/doc/_static/js/badge_only.js +1 -0
- snappy/doc/_static/js/theme.js +1 -0
- snappy/doc/_static/js/versions.js +228 -0
- snappy/doc/_static/language_data.js +3 -101
- snappy/doc/_static/pygments.css +1 -0
- snappy/doc/_static/searchtools.js +489 -398
- snappy/doc/_static/snappy_furo.css +33 -0
- snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
- snappy/doc/_static/sphinx_highlight.js +154 -0
- snappy/doc/additional_classes.html +688 -263
- snappy/doc/bugs.html +107 -94
- snappy/doc/censuses.html +155 -127
- snappy/doc/credits.html +115 -104
- snappy/doc/development.html +184 -146
- snappy/doc/genindex.html +287 -204
- snappy/doc/index.html +189 -150
- snappy/doc/installing.html +259 -266
- snappy/doc/manifold.html +1626 -592
- snappy/doc/manifoldhp.html +119 -105
- snappy/doc/news.html +198 -104
- snappy/doc/objects.inv +0 -0
- snappy/doc/other.html +117 -105
- snappy/doc/platonic_census.html +161 -114
- snappy/doc/plink.html +113 -105
- snappy/doc/ptolemy.html +131 -108
- snappy/doc/ptolemy_classes.html +242 -223
- snappy/doc/ptolemy_examples1.html +144 -130
- snappy/doc/ptolemy_examples2.html +141 -129
- snappy/doc/ptolemy_examples3.html +148 -132
- snappy/doc/ptolemy_examples4.html +131 -111
- snappy/doc/ptolemy_prelim.html +162 -138
- snappy/doc/py-modindex.html +104 -69
- snappy/doc/screenshots.html +117 -108
- snappy/doc/search.html +115 -84
- snappy/doc/searchindex.js +1 -1
- snappy/doc/snap.html +109 -96
- snappy/doc/snappy.html +134 -97
- snappy/doc/spherogram.html +259 -187
- snappy/doc/todo.html +107 -94
- snappy/doc/triangulation.html +1380 -111
- snappy/doc/tutorial.html +107 -94
- snappy/doc/verify.html +194 -125
- snappy/doc/verify_internals.html +248 -686
- snappy/drilling/__init__.py +456 -0
- snappy/drilling/barycentric.py +103 -0
- snappy/drilling/constants.py +5 -0
- snappy/drilling/crush.py +270 -0
- snappy/drilling/cusps.py +125 -0
- snappy/drilling/debug.py +242 -0
- snappy/drilling/epsilons.py +6 -0
- snappy/drilling/exceptions.py +55 -0
- snappy/drilling/moves.py +620 -0
- snappy/drilling/peripheral_curves.py +210 -0
- snappy/drilling/perturb.py +188 -0
- snappy/drilling/shorten.py +36 -0
- snappy/drilling/subdivide.py +274 -0
- snappy/drilling/test.py +23 -0
- snappy/drilling/test_cases.py +126 -0
- snappy/drilling/tracing.py +351 -0
- snappy/exceptions.py +23 -3
- snappy/export_stl.py +20 -14
- snappy/exterior_to_link/__init__.py +2 -0
- snappy/exterior_to_link/barycentric_geometry.py +463 -0
- snappy/exterior_to_link/exceptions.py +6 -0
- snappy/exterior_to_link/geodesic_map.json +14408 -0
- snappy/exterior_to_link/hyp_utils.py +112 -0
- snappy/exterior_to_link/link_projection.py +323 -0
- snappy/exterior_to_link/main.py +197 -0
- snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
- snappy/exterior_to_link/mcomplex_with_link.py +687 -0
- snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
- snappy/exterior_to_link/pl_utils.py +491 -0
- snappy/exterior_to_link/put_in_S3.py +156 -0
- snappy/exterior_to_link/rational_linear_algebra.py +123 -0
- snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
- snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
- snappy/exterior_to_link/stored_moves.py +475 -0
- snappy/exterior_to_link/test.py +31 -0
- snappy/geometric_structure/__init__.py +212 -0
- snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
- snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +697 -0
- snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +484 -0
- snappy/geometric_structure/cusp_neighborhood/exceptions.py +42 -0
- snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +298 -0
- snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +159 -0
- snappy/geometric_structure/cusp_neighborhood/vertices.py +32 -0
- snappy/geometric_structure/geodesic/__init__.py +0 -0
- snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
- snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
- snappy/geometric_structure/geodesic/canonical_keys.py +52 -0
- snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
- snappy/geometric_structure/geodesic/constants.py +6 -0
- snappy/geometric_structure/geodesic/exceptions.py +22 -0
- snappy/geometric_structure/geodesic/fixed_points.py +93 -0
- snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
- snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
- snappy/geometric_structure/geodesic/line.py +30 -0
- snappy/geometric_structure/geodesic/multiplicity.py +127 -0
- snappy/geometric_structure/geodesic/tiles_for_geodesic.py +101 -0
- snappy/geometric_structure/test.py +22 -0
- snappy/gui.py +36 -36
- snappy/horoviewer.py +50 -48
- snappy/hyperboloid/__init__.py +212 -0
- snappy/hyperboloid/distances.py +245 -0
- snappy/hyperboloid/horoball.py +19 -0
- snappy/hyperboloid/line.py +35 -0
- snappy/hyperboloid/point.py +9 -0
- snappy/hyperboloid/triangle.py +29 -0
- snappy/{infodialog.py → infowindow.py} +32 -33
- snappy/isometry_signature.py +382 -0
- snappy/len_spec/__init__.py +596 -0
- snappy/len_spec/geodesic_info.py +110 -0
- snappy/len_spec/geodesic_key_info_dict.py +117 -0
- snappy/len_spec/geodesic_piece.py +143 -0
- snappy/len_spec/geometric_structure.py +182 -0
- snappy/len_spec/geometry.py +80 -0
- snappy/len_spec/length_spectrum_geodesic_info.py +170 -0
- snappy/len_spec/spine.py +206 -0
- snappy/len_spec/test.py +24 -0
- snappy/len_spec/test_cases.py +69 -0
- snappy/len_spec/tile.py +275 -0
- snappy/len_spec/word.py +86 -0
- snappy/manifolds/__init__.py +1 -1
- snappy/math_basics.py +176 -0
- snappy/matrix.py +525 -0
- snappy/number.py +97 -21
- snappy/numeric_output_checker.py +37 -27
- snappy/pari.py +30 -69
- snappy/phone_home.py +25 -20
- snappy/polyviewer.py +39 -37
- snappy/ptolemy/__init__.py +4 -6
- snappy/ptolemy/component.py +14 -12
- snappy/ptolemy/coordinates.py +312 -295
- snappy/ptolemy/fieldExtensions.py +14 -12
- snappy/ptolemy/findLoops.py +43 -31
- snappy/ptolemy/geometricRep.py +24 -26
- snappy/ptolemy/homology.py +12 -7
- snappy/ptolemy/manifoldMethods.py +69 -70
- snappy/ptolemy/matrix.py +65 -26
- snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +18 -14
- snappy/ptolemy/polynomial.py +125 -119
- snappy/ptolemy/processComponents.py +36 -30
- snappy/ptolemy/processFileBase.py +79 -18
- snappy/ptolemy/processFileDispatch.py +13 -14
- snappy/ptolemy/processMagmaFile.py +44 -39
- snappy/ptolemy/processRurFile.py +18 -11
- snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +20 -17
- snappy/ptolemy/ptolemyObstructionClass.py +13 -17
- snappy/ptolemy/ptolemyVariety.py +190 -121
- snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +20 -19
- snappy/ptolemy/reginaWrapper.py +25 -29
- snappy/ptolemy/rur.py +6 -14
- snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +27 -22
- snappy/ptolemy/test.py +247 -188
- snappy/ptolemy/utilities.py +41 -43
- snappy/raytracing/__init__.py +64 -0
- snappy/raytracing/additional_horospheres.py +64 -0
- snappy/raytracing/additional_len_spec_choices.py +63 -0
- snappy/raytracing/cohomology_fractal.py +10 -6
- snappy/raytracing/eyeball.py +123 -0
- snappy/raytracing/finite_raytracing_data.py +48 -38
- snappy/raytracing/finite_viewer.py +218 -210
- snappy/raytracing/geodesic_tube_info.py +174 -0
- snappy/raytracing/geodesics.py +246 -0
- snappy/raytracing/geodesics_window.py +258 -0
- snappy/raytracing/gui_utilities.py +152 -40
- snappy/raytracing/hyperboloid_navigation.py +102 -52
- snappy/raytracing/hyperboloid_utilities.py +114 -261
- snappy/raytracing/ideal_raytracing_data.py +256 -179
- snappy/raytracing/inside_viewer.py +522 -253
- snappy/raytracing/pack.py +22 -0
- snappy/raytracing/raytracing_data.py +46 -34
- snappy/raytracing/raytracing_view.py +190 -109
- snappy/raytracing/shaders/Eye.png +0 -0
- snappy/raytracing/shaders/NonGeometric.png +0 -0
- snappy/raytracing/shaders/__init__.py +60 -4
- snappy/raytracing/shaders/fragment.glsl +575 -148
- snappy/raytracing/test.py +29 -0
- snappy/raytracing/tooltip.py +146 -0
- snappy/raytracing/upper_halfspace_utilities.py +98 -0
- snappy/raytracing/view_scale_controller.py +98 -0
- snappy/raytracing/zoom_slider/__init__.py +32 -29
- snappy/raytracing/zoom_slider/test.py +2 -0
- snappy/sage_helper.py +69 -123
- snappy/{preferences.py → settings.py} +167 -145
- snappy/shell.py +4 -0
- snappy/snap/__init__.py +12 -8
- snappy/snap/character_varieties.py +24 -18
- snappy/snap/find_field.py +35 -34
- snappy/snap/fundamental_polyhedron.py +99 -85
- snappy/snap/generators.py +6 -8
- snappy/snap/interval_reps.py +18 -6
- snappy/snap/kernel_structures.py +8 -3
- snappy/snap/mcomplex_base.py +1 -2
- snappy/snap/nsagetools.py +107 -53
- snappy/snap/peripheral/__init__.py +1 -1
- snappy/snap/peripheral/dual_cellulation.py +15 -7
- snappy/snap/peripheral/link.py +20 -16
- snappy/snap/peripheral/peripheral.py +22 -14
- snappy/snap/peripheral/surface.py +47 -50
- snappy/snap/peripheral/test.py +8 -8
- snappy/snap/polished_reps.py +65 -40
- snappy/snap/shapes.py +41 -22
- snappy/snap/slice_obs_HKL.py +64 -25
- snappy/snap/t3mlite/arrow.py +88 -51
- snappy/snap/t3mlite/corner.py +5 -6
- snappy/snap/t3mlite/edge.py +32 -21
- snappy/snap/t3mlite/face.py +7 -9
- snappy/snap/t3mlite/files.py +31 -23
- snappy/snap/t3mlite/homology.py +14 -10
- snappy/snap/t3mlite/linalg.py +158 -56
- snappy/snap/t3mlite/mcomplex.py +739 -291
- snappy/snap/t3mlite/perm4.py +236 -84
- snappy/snap/t3mlite/setup.py +9 -10
- snappy/snap/t3mlite/simplex.py +65 -48
- snappy/snap/t3mlite/spun.py +42 -30
- snappy/snap/t3mlite/surface.py +45 -45
- snappy/snap/t3mlite/test.py +3 -0
- snappy/snap/t3mlite/test_vs_regina.py +17 -13
- snappy/snap/t3mlite/tetrahedron.py +25 -24
- snappy/snap/t3mlite/vertex.py +8 -13
- snappy/snap/test.py +45 -52
- snappy/snap/utilities.py +66 -65
- snappy/test.py +155 -158
- snappy/test_cases.py +263 -0
- snappy/testing.py +131 -0
- snappy/tiling/__init__.py +2 -0
- snappy/tiling/canonical_key_dict.py +59 -0
- snappy/tiling/dict_based_set.py +79 -0
- snappy/tiling/floor.py +49 -0
- snappy/tiling/hyperboloid_dict.py +54 -0
- snappy/tiling/iter_utils.py +78 -0
- snappy/tiling/lifted_tetrahedron.py +22 -0
- snappy/tiling/lifted_tetrahedron_set.py +54 -0
- snappy/tiling/real_hash_dict.py +164 -0
- snappy/tiling/test.py +23 -0
- snappy/tiling/tile.py +215 -0
- snappy/tiling/triangle.py +33 -0
- snappy/tkterminal.py +313 -203
- snappy/twister/main.py +1 -8
- snappy/twister/twister_core.cpython-38-darwin.so +0 -0
- snappy/upper_halfspace/__init__.py +146 -0
- snappy/upper_halfspace/ideal_point.py +26 -0
- snappy/verify/__init__.py +4 -8
- snappy/verify/{verifyCanonical.py → canonical.py} +114 -97
- snappy/verify/complex_volume/__init__.py +3 -2
- snappy/verify/complex_volume/adjust_torsion.py +13 -11
- snappy/verify/complex_volume/closed.py +29 -24
- snappy/verify/complex_volume/compute_ptolemys.py +8 -6
- snappy/verify/complex_volume/cusped.py +10 -9
- snappy/verify/complex_volume/extended_bloch.py +14 -12
- snappy/verify/{cuspTranslations.py → cusp_translations.py} +15 -14
- snappy/verify/edge_equations.py +80 -0
- snappy/verify/exceptions.py +23 -56
- snappy/verify/{verifyHyperbolicity.py → hyperbolicity.py} +19 -15
- snappy/verify/interval_newton_shapes_engine.py +51 -211
- snappy/verify/interval_tree.py +27 -25
- snappy/verify/krawczyk_shapes_engine.py +47 -50
- snappy/verify/maximal_cusp_area_matrix/__init__.py +17 -86
- snappy/verify/maximal_cusp_area_matrix/cusp_tiling_engine.py +58 -48
- snappy/verify/maximal_cusp_area_matrix/cusp_translate_engine.py +53 -57
- snappy/verify/{realAlgebra.py → real_algebra.py} +26 -20
- snappy/verify/shapes.py +10 -7
- snappy/verify/short_slopes.py +41 -42
- snappy/verify/{squareExtensions.py → square_extensions.py} +96 -92
- snappy/verify/test.py +59 -57
- snappy/verify/upper_halfspace/extended_matrix.py +5 -5
- snappy/verify/upper_halfspace/finite_point.py +44 -31
- snappy/verify/upper_halfspace/ideal_point.py +69 -57
- snappy/verify/volume.py +15 -12
- snappy/version.py +2 -3
- {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/METADATA +14 -12
- snappy-3.2.dist-info/RECORD +503 -0
- {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/WHEEL +1 -1
- {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/entry_points.txt +0 -1
- {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/top_level.txt +10 -1
- snappy/doc/_sources/verify_canon.rst.txt +0 -90
- snappy/doc/_static/classic.css +0 -266
- snappy/doc/_static/jquery-3.5.1.js +0 -10872
- snappy/doc/_static/sidebar.js +0 -159
- snappy/doc/_static/underscore-1.13.1.js +0 -2042
- snappy/doc/_static/underscore.js +0 -6
- snappy/doc/verify_canon.html +0 -283
- snappy/ppm_to_png.py +0 -243
- snappy/togl/__init__.py +0 -3
- snappy/togl/darwin-tk8.6/Togl2.1/LICENSE +0 -28
- snappy/togl/darwin-tk8.6/Togl2.1/libTogl2.1.dylib +0 -0
- snappy/togl/darwin-tk8.6/Togl2.1/pkgIndex.tcl +0 -5
- snappy/togl/linux2-x86_64-tk8.6/Togl2.1/LICENSE +0 -28
- snappy/togl/linux2-x86_64-tk8.6/Togl2.1/libTogl2.1.so +0 -0
- snappy/togl/linux2-x86_64-tk8.6/Togl2.1/pkgIndex.tcl +0 -5
- snappy/togl/win32VC-tk8.6/Togl2.1/LICENSE +0 -28
- snappy/togl/win32VC-tk8.6/Togl2.1/Togl21.dll +0 -0
- snappy/togl/win32VC-tk8.6/Togl2.1/Togl21.lib +0 -0
- snappy/togl/win32VC-tk8.6/Togl2.1/pkgIndex.tcl +0 -6
- snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/LICENSE +0 -28
- snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/Togl21.dll +0 -0
- snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/Togl21.lib +0 -0
- snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/pkgIndex.tcl +0 -6
- snappy/verify/cuspCrossSection.py +0 -1413
- snappy/verify/mathHelpers.py +0 -64
- snappy-3.0.3.dist-info/RECORD +0 -360
snappy/tkterminal.py
CHANGED
@@ -1,35 +1,71 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
import os
|
3
|
-
|
4
|
-
|
5
|
-
from IPython.core.autocall import IPyAutocall
|
6
|
-
import snappy
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import re
|
7
5
|
from urllib.request import pathname2url
|
8
|
-
|
6
|
+
import tkinter as Tk_
|
7
|
+
from tkinter import ttk
|
8
|
+
from tkinter.font import Font
|
9
|
+
from tkinter.font import families as font_families
|
10
|
+
from tkinter.messagebox import askyesno
|
11
|
+
from IPython.utils import io
|
9
12
|
|
10
|
-
|
11
|
-
icon_file = os.path.join(snappy_path, 'info_icon.gif')
|
12
|
-
debug_Tk = False
|
13
|
+
debug_Tk = True
|
13
14
|
ansi_seqs = re.compile(r'(?:\x01*\x1b\[((?:[0-9]*;)*[0-9]*.)\x02*)*([^\x01\x1b]*)',
|
14
15
|
re.MULTILINE)
|
15
|
-
ansi_colors =
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
16
|
+
ansi_colors = {'0;30m': 'Black',
|
17
|
+
'0;31m': 'Red',
|
18
|
+
'0;32m': 'Green',
|
19
|
+
'0;33m': 'Brown',
|
20
|
+
'0;34m': 'Blue',
|
21
|
+
'0;35m': 'Purple',
|
22
|
+
'0;36m': 'Cyan',
|
23
|
+
'0;37m': 'LightGray',
|
24
|
+
'1;30m': 'Black', # 'DarkGray',
|
25
|
+
'1;31m': 'DarkRed',
|
26
|
+
'1;32m': 'SeaGreen',
|
27
|
+
'1;33m': 'Yellow',
|
28
|
+
'1;34m': 'LightBlue',
|
29
|
+
'1;35m': 'MediumPurple',
|
30
|
+
'1;36m': 'LightCyan',
|
31
|
+
'1;37m': 'White'}
|
31
32
|
delims = re.compile(r'[\s\[\]\{\}\(\)\+\-\=\'`~!@#\$\^\&\*]+')
|
32
33
|
|
34
|
+
|
35
|
+
class FontChoice:
|
36
|
+
def __init__(self, family, size, weight, slant):
|
37
|
+
self.family = family
|
38
|
+
self.size = size
|
39
|
+
self.weight = weight
|
40
|
+
self.slant = slant
|
41
|
+
self.rest = f'{self.weight} {self.slant}'
|
42
|
+
|
43
|
+
def as_tuple(self):
|
44
|
+
size = self.size
|
45
|
+
if sys.platform == 'darwin' and Tk_.TkVersion >= 9.0:
|
46
|
+
size = int(size/1.3)
|
47
|
+
return (self.family, size, self.rest)
|
48
|
+
|
49
|
+
def __repr__(self):
|
50
|
+
return 'FontChoice' + repr((self.family, self.size, self.weight, self.slant))
|
51
|
+
|
52
|
+
def bold(self):
|
53
|
+
return FontChoice(self.family, self.size, 'bold', self.slant)
|
54
|
+
|
55
|
+
|
56
|
+
def default_terminal_font():
|
57
|
+
size = 13 if sys.platform == 'darwin' else 11
|
58
|
+
family = Font(font='TkFixedFont').actual()['family']
|
59
|
+
if sys.platform == 'win32':
|
60
|
+
# Default is Courier New which is ugly and appears blurry.
|
61
|
+
available = font_families()
|
62
|
+
for better in ['Consolas', 'Cascadia Mono SemiLight']:
|
63
|
+
if better in available:
|
64
|
+
family = better
|
65
|
+
|
66
|
+
return FontChoice(family, size, 'normal', 'roman')
|
67
|
+
|
68
|
+
|
33
69
|
class Tk(Tk_.Tk):
|
34
70
|
def __init__(self, error_handler=None):
|
35
71
|
Tk_.Tk.__init__(self, className='snappy')
|
@@ -37,14 +73,9 @@ class Tk(Tk_.Tk):
|
|
37
73
|
# calls this function to report their occurrence.
|
38
74
|
if error_handler:
|
39
75
|
self.report_callback_exception = error_handler
|
40
|
-
# In Python 2.7 the _default root does not get set correctly.
|
41
|
-
if not Tk_._default_root:
|
42
|
-
Tk_._default_root = self
|
43
76
|
|
44
|
-
# Some ideas for the TkTerm class were borrowed from code written by
|
45
|
-
# Eitan Isaacson, IBM Corp.
|
46
77
|
|
47
|
-
class
|
78
|
+
class TkTerminalBase:
|
48
79
|
"""
|
49
80
|
A Tkinter terminal window that runs an IPython shell. This class
|
50
81
|
supports the IOStream interface, and can function as a replacement
|
@@ -56,8 +87,6 @@ class TkTerm:
|
|
56
87
|
io.stdout = sys.stdout = self
|
57
88
|
else:
|
58
89
|
self.window = window = Tk(self.report_callback_exception)
|
59
|
-
self.encoding = sys.stdout.encoding
|
60
|
-
self.saved_io = (sys.stdout, sys.stderr)
|
61
90
|
io.stdout = io.stderr = sys.stdout = sys.stderr = self
|
62
91
|
self._input_buffer = ''
|
63
92
|
self._current_indent = 0
|
@@ -65,7 +94,6 @@ class TkTerm:
|
|
65
94
|
window.option_add('*Menu.tearOff', 0)
|
66
95
|
window.title(name)
|
67
96
|
window.protocol("WM_DELETE_WINDOW", self.close)
|
68
|
-
self.icon = Tk_.PhotoImage(file=icon_file)
|
69
97
|
self.frame = frame = Tk_.Frame(window)
|
70
98
|
self.text = text = Tk_.Text(frame,
|
71
99
|
width=85,
|
@@ -77,7 +105,7 @@ class TkTerm:
|
|
77
105
|
highlightthickness=0,
|
78
106
|
relief=Tk_.FLAT
|
79
107
|
)
|
80
|
-
self.set_font(
|
108
|
+
self.set_font(default_terminal_font())
|
81
109
|
self.scroller = scroller = Tk_.Scrollbar(frame, command=text.yview)
|
82
110
|
text.config(yscrollcommand=scroller.set)
|
83
111
|
scroller.pack(side=Tk_.RIGHT, fill=Tk_.Y, pady=10)
|
@@ -85,19 +113,16 @@ class TkTerm:
|
|
85
113
|
frame.pack(fill=Tk_.BOTH, expand=Tk_.YES)
|
86
114
|
text.focus_set()
|
87
115
|
window.bind('<FocusIn>', lambda event=None: text.focus_set())
|
116
|
+
text.bind('<Control-c>', self.handle_control_c)
|
88
117
|
text.bind('<KeyPress>', self.handle_keypress)
|
89
118
|
text.bind('<KeyRelease>', self.handle_keyrelease)
|
90
|
-
if not sys.platform == 'darwin':
|
91
|
-
text.bind('<Control-c>', self.handle_keypress)
|
92
119
|
text.bind('<Return>', self.handle_return)
|
93
120
|
text.bind('<Shift-Return>', self.handle_shift_return)
|
94
121
|
text.bind('<BackSpace>', self.handle_backspace)
|
95
122
|
text.bind('<Delete>', self.handle_backspace)
|
96
123
|
text.bind('<Tab>', self.handle_tab)
|
97
124
|
text.bind('<Up>', self.handle_up)
|
98
|
-
text.bind('<Shift-Up>', lambda event : None)
|
99
125
|
text.bind('<Down>', self.handle_down)
|
100
|
-
text.bind('<Shift-Down>', lambda event : None)
|
101
126
|
text.bind('<Home>', self.go_to_beginning)
|
102
127
|
text.bind('<<Cut>>', self.protect_text)
|
103
128
|
text.bind('<<Copy>>', self.edit_copy)
|
@@ -113,12 +138,14 @@ class TkTerm:
|
|
113
138
|
if sys.platform == 'darwin':
|
114
139
|
self.window.bind_all('<Command-Key-q>', self.close)
|
115
140
|
self.window.bind_all('<Command-Key-Left>', self.go_to_beginning)
|
141
|
+
self.text.bind('<Command-Key-Up>', self.jump_up)
|
116
142
|
elif sys.platform == 'linux2' or sys.platform == 'linux':
|
117
143
|
self.window.bind_all('<Alt-Key-q>', self.close)
|
118
144
|
self.add_bindings()
|
119
145
|
# 'output_end' marks the end of the text written by us.
|
120
146
|
# Everything above this position should be
|
121
147
|
# immutable, and tagged with the "output" style.
|
148
|
+
# Normally it is set at the end of the input prompt.
|
122
149
|
self.text.mark_set('output_end', Tk_.INSERT)
|
123
150
|
self.text.mark_gravity('output_end', Tk_.LEFT)
|
124
151
|
text.tag_config('output')
|
@@ -157,7 +184,7 @@ class TkTerm:
|
|
157
184
|
self.banner = shell.banner1
|
158
185
|
else:
|
159
186
|
cprt = 'Type "copyright", "credits" or "license" for more information.'
|
160
|
-
self.banner = "Python %s on %s\n%s\n(%s)\n" %(
|
187
|
+
self.banner = "Python %s on %s\n%s\n(%s)\n" % (
|
161
188
|
sys.version, sys.platform, cprt,
|
162
189
|
self.__class__.__name__)
|
163
190
|
self.quiet = False
|
@@ -171,6 +198,10 @@ class TkTerm:
|
|
171
198
|
self.showing_traceback = False
|
172
199
|
self.closed = False
|
173
200
|
self._saved_index = Tk_.END
|
201
|
+
# This flag is set to prevent quitting the app.
|
202
|
+
self.blockers = {}
|
203
|
+
self.can_quit = True
|
204
|
+
self.close_callback = lambda :None
|
174
205
|
|
175
206
|
# Emulate a ListedWindow. We are listed, even though we are unique.
|
176
207
|
def bring_to_front(self):
|
@@ -194,12 +225,12 @@ class TkTerm:
|
|
194
225
|
traceback = '\n' + self.IP.InteractiveTB.stb2text(stb)
|
195
226
|
if etype == KeyboardInterrupt:
|
196
227
|
self.write('KeyboardInterrupt: ', style='msg')
|
197
|
-
self.write('%s'%evalue)
|
228
|
+
self.write('%s' % evalue)
|
198
229
|
else:
|
199
230
|
self.write(traceback)
|
200
231
|
self.reset()
|
201
232
|
self.showing_traceback = True
|
202
|
-
self.
|
233
|
+
self.process_return('\n')
|
203
234
|
|
204
235
|
def SnapPea_callback(self, interrupted=False):
|
205
236
|
"""
|
@@ -224,12 +255,14 @@ class TkTerm:
|
|
224
255
|
source_raw = self.reset()
|
225
256
|
self.IP.history_manager.store_inputs(self.IP.execution_count, source_raw)
|
226
257
|
self.IP.execution_count += 1
|
227
|
-
raise KeyboardInterrupt('Halted')
|
228
258
|
else:
|
229
259
|
self.interrupted = True
|
230
260
|
# Inform the SnapPea kernel about the interrupt.
|
231
261
|
snappy.SnapPy.SnapPea_interrupt()
|
232
262
|
snappy.SnapPyHP.SnapPea_interrupt()
|
263
|
+
# For some reason we need to raise a KeyboardInterrupt here. Otherwise
|
264
|
+
# the call to KeyboardInterrupt('Halted') will be ignored.
|
265
|
+
raise KeyboardInterrupt('Interrupted')
|
233
266
|
|
234
267
|
def report_callback_exception(self, exc, value, traceback):
|
235
268
|
"""
|
@@ -240,22 +273,49 @@ class TkTerm:
|
|
240
273
|
sys.last_traceback = traceback
|
241
274
|
self.IP.showtraceback()
|
242
275
|
|
243
|
-
def set_font(self,
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
self.bold_font.config(weight='bold')
|
276
|
+
def set_font(self, font_choice):
|
277
|
+
normal_tuple = font_choice.as_tuple()
|
278
|
+
bold_tuple = font_choice.bold().as_tuple()
|
279
|
+
normal_font = Font(font=font_choice.as_tuple())
|
248
280
|
self.char_size = normal_font.measure('M')
|
281
|
+
self.text.config(font=normal_tuple)
|
249
282
|
text = self.text
|
250
|
-
text.tag_config('output', font=
|
251
|
-
text.tag_config('Prompt', foreground='#0000cc', font=
|
252
|
-
text.tag_config('PromptNum', foreground='#0000bb', font=
|
253
|
-
text.tag_config('OutPrompt', foreground='#cc0000', font=
|
254
|
-
text.tag_config('OutPromptNum', foreground='#bb0000', font=
|
283
|
+
text.tag_config('output', font=normal_tuple)
|
284
|
+
text.tag_config('Prompt', foreground='#0000cc', font=normal_tuple)
|
285
|
+
text.tag_config('PromptNum', foreground='#0000bb', font=bold_tuple)
|
286
|
+
text.tag_config('OutPrompt', foreground='#cc0000', font=normal_tuple)
|
287
|
+
text.tag_config('OutPromptNum', foreground='#bb0000', font=bold_tuple)
|
288
|
+
|
289
|
+
def add_blocker(self, window, message):
|
290
|
+
self.blockers[window] = message
|
291
|
+
|
292
|
+
def remove_blocker(self, window):
|
293
|
+
self.blockers.pop(window)
|
255
294
|
|
256
295
|
def close(self, event=None):
|
257
|
-
|
258
|
-
|
296
|
+
can_quit = True
|
297
|
+
topmost = None
|
298
|
+
for blocker in self.blockers:
|
299
|
+
if blocker.attributes('-topmost'):
|
300
|
+
topmost = blocker
|
301
|
+
blocker.attributes('-topmost', False)
|
302
|
+
message = self.blockers[blocker]
|
303
|
+
answer = askyesno('Quit',
|
304
|
+
message + '\nDo you want to quit anyway?')
|
305
|
+
if not answer:
|
306
|
+
can_quit = False
|
307
|
+
break;
|
308
|
+
if topmost:
|
309
|
+
topmost.attributes('-topmost', True)
|
310
|
+
if can_quit:
|
311
|
+
for blocker in self.blockers:
|
312
|
+
blocker.destroy()
|
313
|
+
self.window.quit()
|
314
|
+
self.closed = True
|
315
|
+
|
316
|
+
def handle_control_c(self, event):
|
317
|
+
self.interrupt()
|
318
|
+
self.interrupted = False
|
259
319
|
|
260
320
|
def handle_keypress(self, event):
|
261
321
|
self.clear_completions()
|
@@ -265,8 +325,27 @@ class TkTerm:
|
|
265
325
|
return
|
266
326
|
keysym = event.keysym
|
267
327
|
if keysym == 'Left':
|
268
|
-
# Don't go
|
269
|
-
|
328
|
+
# Don't go into the prompt or continuation prompt
|
329
|
+
line, pos = map(int, self.text.index(Tk_.INSERT).split('.'))
|
330
|
+
if pos <= self._prompt_size:
|
331
|
+
prompt_line = int(self.text.index('output_end').split('.')[0])
|
332
|
+
insert_line = int(self.text.index(Tk_.INSERT).split('.')[0])
|
333
|
+
if line > prompt_line:
|
334
|
+
self.text.mark_set(Tk_.INSERT, '%s.0-1c' % insert_line)
|
335
|
+
else:
|
336
|
+
self.window.bell()
|
337
|
+
return 'break'
|
338
|
+
return
|
339
|
+
if keysym == 'Right':
|
340
|
+
# Don't go into a continuation prompt or past the end
|
341
|
+
insert_pos = int(self.text.index('%s+1c' % Tk_.INSERT).split('.')[1])
|
342
|
+
if insert_pos < self._prompt_size:
|
343
|
+
insert_line = int(self.text.index(Tk_.INSERT).split('.')[0])
|
344
|
+
if self.text.compare(Tk_.INSERT, '>=', '%s-2c' % Tk_.END):
|
345
|
+
self.window.bell()
|
346
|
+
else:
|
347
|
+
self.text.mark_set(Tk_.INSERT, '%d.%d' % (
|
348
|
+
insert_line + 1, self._prompt_size))
|
270
349
|
return 'break'
|
271
350
|
return
|
272
351
|
# Check for a control character
|
@@ -307,59 +386,62 @@ class TkTerm:
|
|
307
386
|
if self.editing_hist and self.multiline:
|
308
387
|
self.text.tag_add('history', 'output_end', Tk_.INSERT)
|
309
388
|
|
310
|
-
def handle_return(self, event):
|
389
|
+
def handle_return(self, event=None):
|
390
|
+
# If the input consists of one complete line of code we run it,
|
391
|
+
# regardless of where the insert cursor is located. Otherwise we only
|
392
|
+
# run the code if the cursor is at the end of the input
|
311
393
|
self.clear_completions()
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
self.
|
327
|
-
|
328
|
-
|
329
|
-
self.text.
|
330
|
-
self.
|
331
|
-
|
332
|
-
|
394
|
+
if self.running_code:
|
395
|
+
return 'break'
|
396
|
+
cursor = int(self.text.index(Tk_.INSERT).split('.')[0])
|
397
|
+
last = int(self.text.index(Tk_.END).split('.')[0])
|
398
|
+
first = int(self.text.index('output_end').split('.')[0])
|
399
|
+
if cursor == first == last - 1: # single line input
|
400
|
+
self.text.mark_set(Tk_.INSERT, Tk_.END)
|
401
|
+
self.text.insert(Tk_.INSERT, '\n')
|
402
|
+
cell = self.text.get('output_end', Tk_.INSERT)
|
403
|
+
try:
|
404
|
+
self.interact_handle_input(cell)
|
405
|
+
except KeyboardInterrupt:
|
406
|
+
self.write('(IP) Keyboard Interrupt: ')
|
407
|
+
self.reset()
|
408
|
+
self.hist_pointer = 0
|
409
|
+
self.hist_stem = ''
|
410
|
+
self.interact_prompt()
|
411
|
+
self.text.see(Tk_.INSERT)
|
412
|
+
if self.IP.more:
|
413
|
+
self.text.insert(Tk_.INSERT, ' '*self._current_indent, ())
|
414
|
+
self.hist_pointer = 0
|
415
|
+
self.hist_stem = ''
|
333
416
|
return 'break'
|
334
417
|
|
335
418
|
def handle_shift_return(self, event):
|
336
|
-
|
337
|
-
|
338
|
-
l1, c1 = map(int, self.text.index('output_end').split('.'))
|
339
|
-
l2, c2 = map(int, self.text.index(Tk_.INSERT).split('.'))
|
340
|
-
index = '%d.%d'%(l1 + 1, c2 - c1)
|
341
|
-
self.text.delete('output_end', Tk_.END)
|
342
|
-
self.write_history(force_multiline=True)
|
343
|
-
self.text.mark_set(Tk_.INSERT, index)
|
419
|
+
self.text.mark_set(Tk_.INSERT, Tk_.END)
|
420
|
+
return self.handle_return()
|
344
421
|
|
345
|
-
def
|
422
|
+
def jump_up(self, event):
|
423
|
+
return self.handle_up(event, jump=True)
|
424
|
+
|
425
|
+
def handle_up(self, event, jump=False):
|
346
426
|
if self.text.compare(Tk_.INSERT, '<', 'output_end'):
|
347
427
|
return
|
348
|
-
|
349
|
-
|
350
|
-
if
|
428
|
+
insert_line_number = str(self.text.index(Tk_.INSERT)).split('.')[0]
|
429
|
+
prompt_line_number = str(self.text.index('output_end')).split('.')[0]
|
430
|
+
if insert_line_number != prompt_line_number:
|
351
431
|
return
|
352
432
|
if self.hist_pointer == 0:
|
353
433
|
input_history = self.IP.history_manager.input_hist_raw
|
354
434
|
self.hist_stem = self.text.get('output_end', Tk_.END).strip()
|
355
435
|
self.filtered_hist = [x for x in input_history
|
356
|
-
if x.startswith(self.hist_stem)]
|
436
|
+
if x and x.startswith(self.hist_stem)]
|
357
437
|
if self.hist_pointer >= len(self.filtered_hist):
|
358
438
|
self.window.bell()
|
359
439
|
return 'break'
|
360
440
|
self.text.delete('output_end', Tk_.END)
|
361
441
|
self.hist_pointer += 1
|
362
442
|
self.write_history()
|
443
|
+
if jump:
|
444
|
+
self.text.mark_set(Tk_.INSERT, 'output_end')
|
363
445
|
return 'break'
|
364
446
|
|
365
447
|
def handle_down(self, event):
|
@@ -368,11 +450,10 @@ class TkTerm:
|
|
368
450
|
if self.editing_hist:
|
369
451
|
insert_line = int(str(self.text.index(Tk_.INSERT)).split('.')[0])
|
370
452
|
bottom_line = int(str(self.text.index('history_end')).split('.')[0])
|
371
|
-
if insert_line < bottom_line
|
453
|
+
if insert_line < bottom_line:
|
372
454
|
return
|
373
455
|
if self.hist_pointer == 0:
|
374
|
-
|
375
|
-
return 'break'
|
456
|
+
return
|
376
457
|
self.text.delete('output_end', Tk_.END)
|
377
458
|
self.hist_pointer -= 1
|
378
459
|
if self.hist_pointer == 0:
|
@@ -388,6 +469,14 @@ class TkTerm:
|
|
388
469
|
if self.text.compare(Tk_.INSERT, '<=', 'output_end'):
|
389
470
|
self.window.bell()
|
390
471
|
return 'break'
|
472
|
+
line, pos = map(int, self.text.index(Tk_.INSERT).split('.'))
|
473
|
+
first_line = int(self.text.index('output_end').split('.')[0])
|
474
|
+
if pos <= self._prompt_size + 1 and line != first_line:
|
475
|
+
start = '%d.end' % (line - 1)
|
476
|
+
end = '%d.end' % (line)
|
477
|
+
self.text.mark_set(Tk_.INSERT, start)
|
478
|
+
self.text.delete(start, '%s.%s' % (line, self._prompt_size))
|
479
|
+
return 'break'
|
391
480
|
if self._current_indent >= 4:
|
392
481
|
if self.text.get(Tk_.INSERT+'-4c', Tk_.INSERT) == ' ':
|
393
482
|
self.text.delete(Tk_.INSERT+'-4c', Tk_.INSERT)
|
@@ -404,23 +493,35 @@ class TkTerm:
|
|
404
493
|
line = self.text.get('output_end', self.tab_index).strip('\n')
|
405
494
|
word = delims.split(line)[-1]
|
406
495
|
try:
|
407
|
-
completions = self.IP.complete(word)
|
496
|
+
stem, completions = self.IP.complete(word)
|
408
497
|
except TypeError:
|
409
498
|
completions = []
|
410
499
|
if word.find('_') == -1:
|
411
500
|
completions = [x for x in completions
|
412
501
|
if x.find('__') == -1 and x.find('._') == -1]
|
413
|
-
|
502
|
+
# No meaningful completions. Ring the bell.
|
503
|
+
if len(completions) == 0 or len(completions) == 1 and completions[0] == stem:
|
414
504
|
self.window.bell()
|
415
505
|
self.tab_count = 0
|
416
506
|
return 'break'
|
417
|
-
|
418
|
-
if len(
|
419
|
-
self.do_completion(
|
420
|
-
|
421
|
-
|
507
|
+
# Only one completion. Use it.
|
508
|
+
if len(completions) == 1:
|
509
|
+
self.do_completion(stem, completions[0])
|
510
|
+
self.tab_count = 0
|
511
|
+
return 'break'
|
512
|
+
max_stem = self.max_stem(stem, completions)
|
513
|
+
# Add the maximal stem of all completions if it extends the word,
|
514
|
+
if len(max_stem) > len(word):
|
515
|
+
self.do_completion(stem, max_stem)
|
516
|
+
self.tab_count = 0
|
517
|
+
return 'break'
|
518
|
+
# Show the possible completions, with a warning if there are lots.
|
519
|
+
if len(completions) > 60 and self.tab_count == 1:
|
520
|
+
self.show_completions('', '',
|
521
|
+
['%s possibilities -- hit tab again to view them all' %
|
522
|
+
len(completions)])
|
422
523
|
else:
|
423
|
-
self.show_completions(completions)
|
524
|
+
self.show_completions(word, stem, completions)
|
424
525
|
if len(completions) <= 60:
|
425
526
|
self.tab_count += 1
|
426
527
|
return 'break'
|
@@ -429,24 +530,25 @@ class TkTerm:
|
|
429
530
|
self.text.mark_set(Tk_.INSERT, 'output_end')
|
430
531
|
return 'break'
|
431
532
|
|
432
|
-
def do_completion(self,
|
433
|
-
tail = completion[len(
|
533
|
+
def do_completion(self, stem, completion):
|
534
|
+
tail = completion[len(stem):]
|
434
535
|
self.text.insert(self.tab_index, tail)
|
435
536
|
self.tab_index = Tk_.END
|
436
537
|
self.tab_count = 0
|
437
538
|
|
438
|
-
def show_completions(self, comps):
|
539
|
+
def show_completions(self, word, stem, comps):
|
540
|
+
n = len(stem)
|
541
|
+
comps = [word + c[n:] for c in comps]
|
439
542
|
self.text.delete(self.tab_index, Tk_.END)
|
440
543
|
width = self.text.winfo_width()
|
441
|
-
|
442
|
-
charwidth = width//self.char_size
|
544
|
+
charwidth = width // self.char_size
|
443
545
|
biggest = 2 + max([len(x) for x in comps])
|
444
|
-
num_cols = charwidth//biggest
|
445
|
-
num_rows = (len(comps) + num_cols -1)//num_cols
|
546
|
+
num_cols = max(charwidth // biggest, 1)
|
547
|
+
num_rows = (len(comps) + num_cols - 1) // num_cols
|
446
548
|
rows = []
|
447
|
-
format = '%%-%ds'%biggest
|
448
|
-
for n in range(
|
449
|
-
rows.append(''.join(
|
549
|
+
format = '%%-%ds' % biggest
|
550
|
+
for n in range(num_rows):
|
551
|
+
rows.append(''.join(format % x for x in comps[n:len(comps):num_rows]))
|
450
552
|
view = '\n'.join(rows)
|
451
553
|
self.text.insert(self.tab_index, '\n'+view)
|
452
554
|
self.text.mark_set(Tk_.INSERT, self.tab_index)
|
@@ -458,33 +560,40 @@ class TkTerm:
|
|
458
560
|
self.tab_index = None
|
459
561
|
self.tab_count = 0
|
460
562
|
|
461
|
-
def
|
462
|
-
if len(
|
463
|
-
return
|
464
|
-
result =
|
465
|
-
for n in range(1,100):
|
466
|
-
heads =
|
563
|
+
def max_stem(self, stem, completions):
|
564
|
+
if len(completions) == 1:
|
565
|
+
return completions[0]
|
566
|
+
result = stem
|
567
|
+
for n in range(len(stem) + 1, 100):
|
568
|
+
heads = {w[:n] for w in completions}
|
467
569
|
if len(heads) > 1:
|
468
570
|
return result
|
469
571
|
elif len(heads) == 1:
|
470
572
|
result = heads.pop()
|
471
|
-
return
|
573
|
+
return result
|
574
|
+
|
575
|
+
def write_continuation_prompt(self):
|
576
|
+
prompt_tokens = self._continuation_prompt(self._prompt_size)
|
577
|
+
for style, text in prompt_tokens:
|
578
|
+
self.write(text, style, mark=Tk_.INSERT, advance=True)
|
472
579
|
|
473
580
|
def write_history(self, force_multiline=False):
|
474
581
|
self.text.see('output_end')
|
475
582
|
input = self.filtered_hist[-self.hist_pointer]
|
476
583
|
input = re.sub('\n+', '\n', input).rstrip()
|
477
|
-
|
584
|
+
lines = input.split('\n')
|
585
|
+
if len(lines) > 1 or force_multiline:
|
478
586
|
self.editing_hist = True
|
479
587
|
self.multiline = True
|
480
|
-
|
481
|
-
self.write('\n')
|
482
|
-
self.
|
483
|
-
|
484
|
-
|
485
|
-
|
588
|
+
self.text.delete('output_end', Tk_.END)
|
589
|
+
self.write(lines[0] + '\n', mark=Tk_.INSERT, advance=True)
|
590
|
+
prompt_tokens = self._continuation_prompt(self._prompt_size)
|
591
|
+
for line in lines[1:-1]:
|
592
|
+
self.write_continuation_prompt()
|
593
|
+
self.write(line + '\n', mark=Tk_.INSERT)
|
594
|
+
self.write_continuation_prompt()
|
595
|
+
self.write(lines[-1], mark=Tk_.INSERT)
|
486
596
|
self.text.mark_set('history_end', Tk_.INSERT)
|
487
|
-
self.text.mark_set(Tk_.INSERT, 'output_end')
|
488
597
|
else:
|
489
598
|
self.multiline = False
|
490
599
|
self.write(input, style=(), advance=False)
|
@@ -605,33 +714,20 @@ class TkTerm:
|
|
605
714
|
|
606
715
|
def start_interaction(self):
|
607
716
|
"""
|
608
|
-
|
717
|
+
Display a banner and prepare to begin interaction.
|
609
718
|
"""
|
610
|
-
|
611
|
-
banner_label = Tk_.Label(self.text,
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
justify=Tk_.LEFT,
|
616
|
-
font=self.prefs['font'])
|
719
|
+
# Subclasses should override this method
|
720
|
+
banner_label = Tk_.Label(self.text,
|
721
|
+
text="Please override the start_interaction method.",
|
722
|
+
anchor=Tk_.W,
|
723
|
+
justify=Tk_.LEFT)
|
617
724
|
self.text.window_create(Tk_.END, window=banner_label)
|
618
725
|
self.text.insert(Tk_.END, '\n')
|
619
726
|
self.text.mark_set('output_end', '2.0')
|
620
|
-
# Set a reasonable default directory for files to be saved to.
|
621
|
-
try:
|
622
|
-
home = os.environ['HOME']
|
623
|
-
except KeyError:
|
624
|
-
home = os.path.expanduser("~")
|
625
|
-
desktop = os.path.join(home, "Desktop")
|
626
|
-
default_save_dir = desktop if os.path.exists(desktop) else home
|
627
|
-
self.IP.magics_manager.magics['line']['cd']("-q " + default_save_dir)
|
628
|
-
# Create the prompt and go!
|
629
|
-
self.interact_prompt()
|
630
|
-
self.text.mark_set('output_end',Tk_.INSERT)
|
631
727
|
|
632
728
|
def _input_prompt(self):
|
633
729
|
result = [('Prompt', 'In['),
|
634
|
-
('PromptNum', '%d'%self.IP.execution_count),
|
730
|
+
('PromptNum', '%d' % self.IP.execution_count),
|
635
731
|
('Prompt', ']: ')]
|
636
732
|
self._prompt_size = sum(len(token[1]) for token in result)
|
637
733
|
return result
|
@@ -642,57 +738,90 @@ class TkTerm:
|
|
642
738
|
|
643
739
|
def interact_prompt(self):
|
644
740
|
"""
|
645
|
-
Print an input prompt or a continuation prompt.
|
741
|
+
Print an input prompt or a continuation prompt. For an input
|
742
|
+
prompt set the output_end mark at the end of the prompt.
|
646
743
|
"""
|
647
744
|
if self.showing_traceback:
|
648
745
|
self.showing_traceback = False
|
649
746
|
return
|
650
747
|
try:
|
651
|
-
if self.IP.more:
|
652
|
-
|
748
|
+
if self.IP.more or self.editing_hist:
|
749
|
+
self.write_continuation_prompt()
|
653
750
|
else:
|
654
|
-
self.
|
751
|
+
if int(self.text.index('output_end').split('.')[1]) != 0:
|
752
|
+
self.write('\n\n', mark='output_end')
|
655
753
|
prompt_tokens = self._input_prompt()
|
754
|
+
for style, text in prompt_tokens:
|
755
|
+
self.write(text, style, mark='output_end')
|
656
756
|
except:
|
657
757
|
self.IP.showtraceback()
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
758
|
+
|
759
|
+
def clean_code(self, code):
|
760
|
+
"""
|
761
|
+
Remove blank lines and continuation prompts.
|
762
|
+
"""
|
763
|
+
if not code.strip():
|
764
|
+
return '\n'
|
765
|
+
lines = list(code.split('\n'))
|
766
|
+
clean_lines = [lines[0].lstrip()]
|
767
|
+
for line in lines[1:]:
|
768
|
+
try:
|
769
|
+
clean_lines.append(line.split(': ', 1)[1])
|
770
|
+
except IndexError:
|
771
|
+
pass
|
772
|
+
return '\n'.join(clean_lines)
|
773
|
+
|
774
|
+
def interact_handle_input(self, cell, script=False):
|
775
|
+
"""
|
776
|
+
Validate the code in the cell. If the code is valid but
|
777
|
+
incomplete, set the indent that should follow a continuation
|
778
|
+
prompt and set the 'more' flag. If the code is valid and
|
779
|
+
complete then run the code.
|
780
|
+
"""
|
781
|
+
assert cell.endswith('\n')
|
782
|
+
if not cell.strip():
|
783
|
+
self._current_indent = 0
|
784
|
+
return
|
667
785
|
if script:
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
status, indent = Xstatus, Xindent
|
786
|
+
self._input_buffer += cell
|
787
|
+
else:
|
788
|
+
self._input_buffer = self.clean_code(cell)
|
789
|
+
transformed_cell = self.IP.transform_cell(self._input_buffer)
|
790
|
+
status, indent = self.IP.check_complete(transformed_cell)
|
791
|
+
self._current_indent = indent or 0
|
675
792
|
if status == 'incomplete':
|
676
793
|
self.IP.more = True
|
677
|
-
self._current_indent = indent or 0
|
678
794
|
return
|
679
795
|
if status == 'invalid':
|
680
796
|
# Force display of the SyntaxError
|
797
|
+
self.text.mark_set(Tk_.INSERT, self.text.index('output_end-1line'))
|
681
798
|
self.IP.run_cell(self._input_buffer, store_history=True)
|
799
|
+
self.text.insert('output_end-1line', '\n')
|
682
800
|
self.reset()
|
801
|
+
self.text.delete('output_end', Tk_.END)
|
683
802
|
return
|
684
|
-
# The code is complete, but we only run it if the
|
685
|
-
#
|
686
|
-
|
687
|
-
|
688
|
-
|
803
|
+
# The code is complete, but we only run it if the cursor is on the
|
804
|
+
# last line of the input and that line is blank.
|
805
|
+
insert_line = int(self.text.index(Tk_.INSERT).split('.')[0])
|
806
|
+
prompt_line = int(self.text.index('output_end').split('.')[0])
|
807
|
+
tail = self.text.get('%d.%d' % (insert_line, self._prompt_size), Tk_.END)
|
808
|
+
if not tail.strip():
|
689
809
|
self.text.tag_delete('history')
|
690
810
|
self._input_buffer = self._input_buffer.rstrip() + '\n'
|
691
|
-
|
692
|
-
|
811
|
+
self.text.delete(Tk_.INSERT, Tk_.END)
|
812
|
+
self.text.insert(Tk_.INSERT, '\n')
|
813
|
+
self.text.mark_set('output_end', Tk_.INSERT)
|
814
|
+
self.multiline = False
|
693
815
|
self.running_code = True
|
694
|
-
|
816
|
+
self.editing_hist = False
|
817
|
+
last_line = insert_line - 1
|
818
|
+
if last_line > prompt_line:
|
819
|
+
# Delete the last continuation prompt.
|
820
|
+
self.text.delete('%d.0' % last_line, '%d.0 lineend' % last_line)
|
821
|
+
self.IP.run_cell(self._input_buffer, store_history=True)
|
822
|
+
# Add a newline after the output.
|
695
823
|
self.write('\n')
|
824
|
+
self.text.tag_add('output', 'output_end', Tk_.END)
|
696
825
|
self.reset()
|
697
826
|
else:
|
698
827
|
self.IP.more = True
|
@@ -706,29 +835,9 @@ class TkTerm:
|
|
706
835
|
self.multiline = False
|
707
836
|
self.running_code = False
|
708
837
|
self.IP.more = False
|
709
|
-
|
710
838
|
self.text.tag_delete('history')
|
711
839
|
return result
|
712
840
|
|
713
|
-
def send_code(self, code):
|
714
|
-
"""
|
715
|
-
Accumulate some lines of code and either issue a continuation
|
716
|
-
prompt or execute the code, print the result and issue a new
|
717
|
-
input prompt.
|
718
|
-
"""
|
719
|
-
try:
|
720
|
-
self.interact_handle_input(code)
|
721
|
-
except KeyboardInterrupt:
|
722
|
-
self.write('(IP) Keyboard Interrupt: ')
|
723
|
-
self.reset()
|
724
|
-
self.interact_prompt()
|
725
|
-
self.text.see(Tk_.INSERT)
|
726
|
-
self.text.mark_set('output_end',Tk_.INSERT)
|
727
|
-
if self.IP.more:
|
728
|
-
self.text.insert(Tk_.INSERT, ' '*self._current_indent, ())
|
729
|
-
self.hist_pointer = 0
|
730
|
-
self.hist_stem = ''
|
731
|
-
|
732
841
|
def write(self, string, style=('output',), advance=True,
|
733
842
|
mark='output_end', see=True):
|
734
843
|
"""
|
@@ -738,10 +847,11 @@ class TkTerm:
|
|
738
847
|
"""
|
739
848
|
if self.quiet:
|
740
849
|
return
|
741
|
-
#if self.interrupted:
|
850
|
+
# if self.interrupted:
|
742
851
|
# self.interrupted = False
|
743
852
|
# raise KeyboardInterrupt('Writing')
|
744
|
-
|
853
|
+
if mark != Tk_.INSERT:
|
854
|
+
self.text.mark_set(Tk_.INSERT, mark)
|
745
855
|
pairs = ansi_seqs.findall(string)
|
746
856
|
for pair in pairs:
|
747
857
|
code, text = pair
|
@@ -754,13 +864,14 @@ class TkTerm:
|
|
754
864
|
if see:
|
755
865
|
self.text.see(Tk_.INSERT)
|
756
866
|
# Give the Text widget a chance to update itself every
|
757
|
-
# so often
|
867
|
+
# so often. In order to force processing of key events
|
868
|
+
# we have to call the evil update method, unfortunately.
|
758
869
|
if self.output_count > 2000:
|
759
870
|
self.output_count = 0
|
760
|
-
self.text.
|
871
|
+
self.text.update()
|
761
872
|
if self.interrupted:
|
762
873
|
self.interrupted = False
|
763
|
-
|
874
|
+
raise KeyboardInterrupt('Halted')
|
764
875
|
|
765
876
|
def write2(self, string):
|
766
877
|
"""
|
@@ -802,7 +913,6 @@ class TkTerm:
|
|
802
913
|
# else:
|
803
914
|
# self.text.mark_set(Tk_.INSERT, '%s.0'%(insert_line + scroll_amount))
|
804
915
|
|
805
|
-
|
806
916
|
def flush(self):
|
807
917
|
"""
|
808
918
|
Required for a stdout / stderr proxy.
|