passagemath-singular 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-singular might be problematic. Click here for more details.

Files changed (493) hide show
  1. PySingular.cpython-314-x86_64-linux-musl.so +0 -0
  2. passagemath_singular-10.6.31rc3.dist-info/METADATA +183 -0
  3. passagemath_singular-10.6.31rc3.dist-info/RECORD +493 -0
  4. passagemath_singular-10.6.31rc3.dist-info/WHEEL +5 -0
  5. passagemath_singular-10.6.31rc3.dist-info/top_level.txt +3 -0
  6. passagemath_singular.libs/libSingular-4-67059f19.4.1.so +0 -0
  7. passagemath_singular.libs/libcddgmp-30166d29.so.0.1.3 +0 -0
  8. passagemath_singular.libs/libfactory-4-9d37bcf4.4.1.so +0 -0
  9. passagemath_singular.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
  10. passagemath_singular.libs/libgcc_s-0cd532bd.so.1 +0 -0
  11. passagemath_singular.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
  12. passagemath_singular.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  13. passagemath_singular.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  14. passagemath_singular.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  15. passagemath_singular.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  16. passagemath_singular.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
  17. passagemath_singular.libs/libntl-26885ca2.so.44.0.1 +0 -0
  18. passagemath_singular.libs/libomalloc-0-e9ff96db.9.6.so +0 -0
  19. passagemath_singular.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  20. passagemath_singular.libs/libpolys-4-8bcf8e7d.4.1.so +0 -0
  21. passagemath_singular.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  22. passagemath_singular.libs/libreadline-06542304.so.8.2 +0 -0
  23. passagemath_singular.libs/libsingular_resources-4-73bf7623.4.1.so +0 -0
  24. passagemath_singular.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  25. sage/algebras/all__sagemath_singular.py +3 -0
  26. sage/algebras/fusion_rings/all.py +19 -0
  27. sage/algebras/fusion_rings/f_matrix.py +2448 -0
  28. sage/algebras/fusion_rings/fast_parallel_fmats_methods.cpython-314-x86_64-linux-musl.so +0 -0
  29. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pxd +5 -0
  30. sage/algebras/fusion_rings/fast_parallel_fmats_methods.pyx +538 -0
  31. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.cpython-314-x86_64-linux-musl.so +0 -0
  32. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pxd +3 -0
  33. sage/algebras/fusion_rings/fast_parallel_fusion_ring_braid_repn.pyx +331 -0
  34. sage/algebras/fusion_rings/fusion_double.py +899 -0
  35. sage/algebras/fusion_rings/fusion_ring.py +1580 -0
  36. sage/algebras/fusion_rings/poly_tup_engine.cpython-314-x86_64-linux-musl.so +0 -0
  37. sage/algebras/fusion_rings/poly_tup_engine.pxd +24 -0
  38. sage/algebras/fusion_rings/poly_tup_engine.pyx +579 -0
  39. sage/algebras/fusion_rings/shm_managers.cpython-314-x86_64-linux-musl.so +0 -0
  40. sage/algebras/fusion_rings/shm_managers.pxd +24 -0
  41. sage/algebras/fusion_rings/shm_managers.pyx +780 -0
  42. sage/algebras/letterplace/all.py +1 -0
  43. sage/algebras/letterplace/free_algebra_element_letterplace.cpython-314-x86_64-linux-musl.so +0 -0
  44. sage/algebras/letterplace/free_algebra_element_letterplace.pxd +18 -0
  45. sage/algebras/letterplace/free_algebra_element_letterplace.pyx +755 -0
  46. sage/algebras/letterplace/free_algebra_letterplace.cpython-314-x86_64-linux-musl.so +0 -0
  47. sage/algebras/letterplace/free_algebra_letterplace.pxd +35 -0
  48. sage/algebras/letterplace/free_algebra_letterplace.pyx +914 -0
  49. sage/algebras/letterplace/letterplace_ideal.cpython-314-x86_64-linux-musl.so +0 -0
  50. sage/algebras/letterplace/letterplace_ideal.pyx +408 -0
  51. sage/algebras/quatalg/all.py +2 -0
  52. sage/algebras/quatalg/quaternion_algebra.py +4778 -0
  53. sage/algebras/quatalg/quaternion_algebra_cython.cpython-314-x86_64-linux-musl.so +0 -0
  54. sage/algebras/quatalg/quaternion_algebra_cython.pyx +261 -0
  55. sage/algebras/quatalg/quaternion_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  56. sage/algebras/quatalg/quaternion_algebra_element.pxd +29 -0
  57. sage/algebras/quatalg/quaternion_algebra_element.pyx +2176 -0
  58. sage/all__sagemath_singular.py +11 -0
  59. sage/ext_data/all__sagemath_singular.py +1 -0
  60. sage/ext_data/singular/function_field/core.lib +98 -0
  61. sage/interfaces/all__sagemath_singular.py +1 -0
  62. sage/interfaces/singular.py +2835 -0
  63. sage/libs/all__sagemath_singular.py +1 -0
  64. sage/libs/singular/__init__.py +1 -0
  65. sage/libs/singular/decl.pxd +1168 -0
  66. sage/libs/singular/function.cpython-314-x86_64-linux-musl.so +0 -0
  67. sage/libs/singular/function.pxd +87 -0
  68. sage/libs/singular/function.pyx +1901 -0
  69. sage/libs/singular/function_factory.py +61 -0
  70. sage/libs/singular/groebner_strategy.cpython-314-x86_64-linux-musl.so +0 -0
  71. sage/libs/singular/groebner_strategy.pxd +22 -0
  72. sage/libs/singular/groebner_strategy.pyx +582 -0
  73. sage/libs/singular/option.cpython-314-x86_64-linux-musl.so +0 -0
  74. sage/libs/singular/option.pyx +671 -0
  75. sage/libs/singular/polynomial.cpython-314-x86_64-linux-musl.so +0 -0
  76. sage/libs/singular/polynomial.pxd +39 -0
  77. sage/libs/singular/polynomial.pyx +661 -0
  78. sage/libs/singular/ring.cpython-314-x86_64-linux-musl.so +0 -0
  79. sage/libs/singular/ring.pxd +58 -0
  80. sage/libs/singular/ring.pyx +893 -0
  81. sage/libs/singular/singular.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/libs/singular/singular.pxd +72 -0
  83. sage/libs/singular/singular.pyx +1944 -0
  84. sage/libs/singular/standard_options.py +145 -0
  85. sage/matrix/all__sagemath_singular.py +1 -0
  86. sage/matrix/matrix_mpolynomial_dense.cpython-314-x86_64-linux-musl.so +0 -0
  87. sage/matrix/matrix_mpolynomial_dense.pxd +7 -0
  88. sage/matrix/matrix_mpolynomial_dense.pyx +615 -0
  89. sage/rings/all__sagemath_singular.py +1 -0
  90. sage/rings/function_field/all__sagemath_singular.py +1 -0
  91. sage/rings/function_field/derivations_polymod.py +911 -0
  92. sage/rings/function_field/element_polymod.cpython-314-x86_64-linux-musl.so +0 -0
  93. sage/rings/function_field/element_polymod.pyx +406 -0
  94. sage/rings/function_field/function_field_polymod.py +2611 -0
  95. sage/rings/function_field/ideal_polymod.py +1775 -0
  96. sage/rings/function_field/order_polymod.py +1475 -0
  97. sage/rings/function_field/place_polymod.py +681 -0
  98. sage/rings/polynomial/all__sagemath_singular.py +1 -0
  99. sage/rings/polynomial/multi_polynomial_ideal_libsingular.cpython-314-x86_64-linux-musl.so +0 -0
  100. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pxd +5 -0
  101. sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +339 -0
  102. sage/rings/polynomial/multi_polynomial_libsingular.cpython-314-x86_64-linux-musl.so +0 -0
  103. sage/rings/polynomial/multi_polynomial_libsingular.pxd +30 -0
  104. sage/rings/polynomial/multi_polynomial_libsingular.pyx +6277 -0
  105. sage/rings/polynomial/plural.cpython-314-x86_64-linux-musl.so +0 -0
  106. sage/rings/polynomial/plural.pxd +48 -0
  107. sage/rings/polynomial/plural.pyx +3171 -0
  108. sage/symbolic/all__sagemath_singular.py +1 -0
  109. sage/symbolic/comparison_impl.pxi +428 -0
  110. sage/symbolic/constants_c_impl.pxi +178 -0
  111. sage/symbolic/expression.cpython-314-x86_64-linux-musl.so +0 -0
  112. sage/symbolic/expression.pxd +7 -0
  113. sage/symbolic/expression.pyx +14200 -0
  114. sage/symbolic/getitem_impl.pxi +202 -0
  115. sage/symbolic/pynac.pxi +572 -0
  116. sage/symbolic/pynac_constant_impl.pxi +133 -0
  117. sage/symbolic/pynac_function_impl.pxi +206 -0
  118. sage/symbolic/pynac_impl.pxi +2576 -0
  119. sage/symbolic/pynac_wrap.h +124 -0
  120. sage/symbolic/series_impl.pxi +272 -0
  121. sage/symbolic/substitution_map_impl.pxi +94 -0
  122. sage_wheels/bin/ESingular +0 -0
  123. sage_wheels/bin/Singular +0 -0
  124. sage_wheels/bin/TSingular +0 -0
  125. sage_wheels/lib/singular/MOD/cohomo.la +41 -0
  126. sage_wheels/lib/singular/MOD/cohomo.so +0 -0
  127. sage_wheels/lib/singular/MOD/customstd.la +41 -0
  128. sage_wheels/lib/singular/MOD/customstd.so +0 -0
  129. sage_wheels/lib/singular/MOD/freealgebra.la +41 -0
  130. sage_wheels/lib/singular/MOD/freealgebra.so +0 -0
  131. sage_wheels/lib/singular/MOD/gfanlib.la +41 -0
  132. sage_wheels/lib/singular/MOD/gfanlib.so +0 -0
  133. sage_wheels/lib/singular/MOD/gitfan.la +41 -0
  134. sage_wheels/lib/singular/MOD/gitfan.so +0 -0
  135. sage_wheels/lib/singular/MOD/interval.la +41 -0
  136. sage_wheels/lib/singular/MOD/interval.so +0 -0
  137. sage_wheels/lib/singular/MOD/loctriv.la +41 -0
  138. sage_wheels/lib/singular/MOD/loctriv.so +0 -0
  139. sage_wheels/lib/singular/MOD/machinelearning.la +41 -0
  140. sage_wheels/lib/singular/MOD/machinelearning.so +0 -0
  141. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.la +41 -0
  142. sage_wheels/lib/singular/MOD/p_Procs_FieldGeneral.so +0 -0
  143. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.la +41 -0
  144. sage_wheels/lib/singular/MOD/p_Procs_FieldIndep.so +0 -0
  145. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.la +41 -0
  146. sage_wheels/lib/singular/MOD/p_Procs_FieldQ.so +0 -0
  147. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.la +41 -0
  148. sage_wheels/lib/singular/MOD/p_Procs_FieldZp.so +0 -0
  149. sage_wheels/lib/singular/MOD/partialgb.la +41 -0
  150. sage_wheels/lib/singular/MOD/partialgb.so +0 -0
  151. sage_wheels/lib/singular/MOD/pyobject.la +41 -0
  152. sage_wheels/lib/singular/MOD/pyobject.so +0 -0
  153. sage_wheels/lib/singular/MOD/singmathic.la +41 -0
  154. sage_wheels/lib/singular/MOD/singmathic.so +0 -0
  155. sage_wheels/lib/singular/MOD/sispasm.la +41 -0
  156. sage_wheels/lib/singular/MOD/sispasm.so +0 -0
  157. sage_wheels/lib/singular/MOD/subsets.la +41 -0
  158. sage_wheels/lib/singular/MOD/subsets.so +0 -0
  159. sage_wheels/lib/singular/MOD/systhreads.la +41 -0
  160. sage_wheels/lib/singular/MOD/systhreads.so +0 -0
  161. sage_wheels/lib/singular/MOD/syzextra.la +41 -0
  162. sage_wheels/lib/singular/MOD/syzextra.so +0 -0
  163. sage_wheels/libexec/singular/MOD/change_cost +0 -0
  164. sage_wheels/libexec/singular/MOD/singularsurf +11 -0
  165. sage_wheels/libexec/singular/MOD/singularsurf_jupyter +9 -0
  166. sage_wheels/libexec/singular/MOD/singularsurf_win +10 -0
  167. sage_wheels/libexec/singular/MOD/solve_IP +0 -0
  168. sage_wheels/libexec/singular/MOD/surfex +16 -0
  169. sage_wheels/libexec/singular/MOD/toric_ideal +0 -0
  170. sage_wheels/share/factory/gftables/10201 +342 -0
  171. sage_wheels/share/factory/gftables/1024 +37 -0
  172. sage_wheels/share/factory/gftables/10609 +356 -0
  173. sage_wheels/share/factory/gftables/11449 +384 -0
  174. sage_wheels/share/factory/gftables/11881 +398 -0
  175. sage_wheels/share/factory/gftables/121 +6 -0
  176. sage_wheels/share/factory/gftables/12167 +408 -0
  177. sage_wheels/share/factory/gftables/125 +7 -0
  178. sage_wheels/share/factory/gftables/12769 +428 -0
  179. sage_wheels/share/factory/gftables/128 +7 -0
  180. sage_wheels/share/factory/gftables/1331 +47 -0
  181. sage_wheels/share/factory/gftables/1369 +48 -0
  182. sage_wheels/share/factory/gftables/14641 +490 -0
  183. sage_wheels/share/factory/gftables/15625 +523 -0
  184. sage_wheels/share/factory/gftables/16 +3 -0
  185. sage_wheels/share/factory/gftables/16129 +540 -0
  186. sage_wheels/share/factory/gftables/16384 +549 -0
  187. sage_wheels/share/factory/gftables/16807 +563 -0
  188. sage_wheels/share/factory/gftables/1681 +58 -0
  189. sage_wheels/share/factory/gftables/169 +8 -0
  190. sage_wheels/share/factory/gftables/17161 +574 -0
  191. sage_wheels/share/factory/gftables/1849 +64 -0
  192. sage_wheels/share/factory/gftables/18769 +628 -0
  193. sage_wheels/share/factory/gftables/19321 +646 -0
  194. sage_wheels/share/factory/gftables/19683 +659 -0
  195. sage_wheels/share/factory/gftables/2048 +71 -0
  196. sage_wheels/share/factory/gftables/2187 +75 -0
  197. sage_wheels/share/factory/gftables/2197 +76 -0
  198. sage_wheels/share/factory/gftables/2209 +76 -0
  199. sage_wheels/share/factory/gftables/22201 +742 -0
  200. sage_wheels/share/factory/gftables/22801 +762 -0
  201. sage_wheels/share/factory/gftables/2401 +82 -0
  202. sage_wheels/share/factory/gftables/243 +11 -0
  203. sage_wheels/share/factory/gftables/24389 +815 -0
  204. sage_wheels/share/factory/gftables/24649 +824 -0
  205. sage_wheels/share/factory/gftables/25 +3 -0
  206. sage_wheels/share/factory/gftables/256 +11 -0
  207. sage_wheels/share/factory/gftables/26569 +888 -0
  208. sage_wheels/share/factory/gftables/27 +3 -0
  209. sage_wheels/share/factory/gftables/27889 +932 -0
  210. sage_wheels/share/factory/gftables/2809 +96 -0
  211. sage_wheels/share/factory/gftables/28561 +954 -0
  212. sage_wheels/share/factory/gftables/289 +12 -0
  213. sage_wheels/share/factory/gftables/29791 +995 -0
  214. sage_wheels/share/factory/gftables/29929 +1000 -0
  215. sage_wheels/share/factory/gftables/3125 +107 -0
  216. sage_wheels/share/factory/gftables/32 +4 -0
  217. sage_wheels/share/factory/gftables/32041 +1070 -0
  218. sage_wheels/share/factory/gftables/32761 +1094 -0
  219. sage_wheels/share/factory/gftables/32768 +1095 -0
  220. sage_wheels/share/factory/gftables/343 +14 -0
  221. sage_wheels/share/factory/gftables/3481 +118 -0
  222. sage_wheels/share/factory/gftables/361 +14 -0
  223. sage_wheels/share/factory/gftables/36481 +1218 -0
  224. sage_wheels/share/factory/gftables/3721 +126 -0
  225. sage_wheels/share/factory/gftables/37249 +1244 -0
  226. sage_wheels/share/factory/gftables/38809 +1296 -0
  227. sage_wheels/share/factory/gftables/39601 +1322 -0
  228. sage_wheels/share/factory/gftables/4 +3 -0
  229. sage_wheels/share/factory/gftables/4096 +139 -0
  230. sage_wheels/share/factory/gftables/44521 +1486 -0
  231. sage_wheels/share/factory/gftables/4489 +152 -0
  232. sage_wheels/share/factory/gftables/49 +4 -0
  233. sage_wheels/share/factory/gftables/4913 +166 -0
  234. sage_wheels/share/factory/gftables/49729 +1660 -0
  235. sage_wheels/share/factory/gftables/5041 +170 -0
  236. sage_wheels/share/factory/gftables/50653 +1691 -0
  237. sage_wheels/share/factory/gftables/512 +20 -0
  238. sage_wheels/share/factory/gftables/51529 +1720 -0
  239. sage_wheels/share/factory/gftables/52441 +1750 -0
  240. sage_wheels/share/factory/gftables/529 +20 -0
  241. sage_wheels/share/factory/gftables/5329 +180 -0
  242. sage_wheels/share/factory/gftables/54289 +1812 -0
  243. sage_wheels/share/factory/gftables/57121 +1906 -0
  244. sage_wheels/share/factory/gftables/58081 +1938 -0
  245. sage_wheels/share/factory/gftables/59049 +1971 -0
  246. sage_wheels/share/factory/gftables/6241 +210 -0
  247. sage_wheels/share/factory/gftables/625 +23 -0
  248. sage_wheels/share/factory/gftables/63001 +2102 -0
  249. sage_wheels/share/factory/gftables/64 +5 -0
  250. sage_wheels/share/factory/gftables/6561 +221 -0
  251. sage_wheels/share/factory/gftables/6859 +231 -0
  252. sage_wheels/share/factory/gftables/6889 +232 -0
  253. sage_wheels/share/factory/gftables/729 +27 -0
  254. sage_wheels/share/factory/gftables/7921 +266 -0
  255. sage_wheels/share/factory/gftables/8 +3 -0
  256. sage_wheels/share/factory/gftables/81 +5 -0
  257. sage_wheels/share/factory/gftables/8192 +276 -0
  258. sage_wheels/share/factory/gftables/841 +30 -0
  259. sage_wheels/share/factory/gftables/9 +3 -0
  260. sage_wheels/share/factory/gftables/9409 +316 -0
  261. sage_wheels/share/factory/gftables/961 +34 -0
  262. sage_wheels/share/info/singular.info +191898 -0
  263. sage_wheels/share/singular/LIB/GND.lib +1359 -0
  264. sage_wheels/share/singular/LIB/JMBTest.lib +976 -0
  265. sage_wheels/share/singular/LIB/JMSConst.lib +1363 -0
  266. sage_wheels/share/singular/LIB/KVequiv.lib +699 -0
  267. sage_wheels/share/singular/LIB/SingularityDBM.lib +491 -0
  268. sage_wheels/share/singular/LIB/VecField.lib +1542 -0
  269. sage_wheels/share/singular/LIB/absfact.lib +959 -0
  270. sage_wheels/share/singular/LIB/ainvar.lib +730 -0
  271. sage_wheels/share/singular/LIB/aksaka.lib +419 -0
  272. sage_wheels/share/singular/LIB/alexpoly.lib +2542 -0
  273. sage_wheels/share/singular/LIB/algebra.lib +1193 -0
  274. sage_wheels/share/singular/LIB/all.lib +136 -0
  275. sage_wheels/share/singular/LIB/arcpoint.lib +514 -0
  276. sage_wheels/share/singular/LIB/arnold.lib +4553 -0
  277. sage_wheels/share/singular/LIB/arnoldclassify.lib +2058 -0
  278. sage_wheels/share/singular/LIB/arr.lib +3486 -0
  279. sage_wheels/share/singular/LIB/assprimeszerodim.lib +755 -0
  280. sage_wheels/share/singular/LIB/autgradalg.lib +3361 -0
  281. sage_wheels/share/singular/LIB/bfun.lib +1964 -0
  282. sage_wheels/share/singular/LIB/bimodules.lib +774 -0
  283. sage_wheels/share/singular/LIB/brillnoether.lib +226 -0
  284. sage_wheels/share/singular/LIB/brnoeth.lib +5017 -0
  285. sage_wheels/share/singular/LIB/central.lib +2169 -0
  286. sage_wheels/share/singular/LIB/chern.lib +4162 -0
  287. sage_wheels/share/singular/LIB/cimonom.lib +571 -0
  288. sage_wheels/share/singular/LIB/cisimplicial.lib +1835 -0
  289. sage_wheels/share/singular/LIB/classify.lib +3239 -0
  290. sage_wheels/share/singular/LIB/classify2.lib +1462 -0
  291. sage_wheels/share/singular/LIB/classifyMapGerms.lib +1515 -0
  292. sage_wheels/share/singular/LIB/classify_aeq.lib +3253 -0
  293. sage_wheels/share/singular/LIB/classifyceq.lib +2092 -0
  294. sage_wheels/share/singular/LIB/classifyci.lib +1133 -0
  295. sage_wheels/share/singular/LIB/combinat.lib +91 -0
  296. sage_wheels/share/singular/LIB/compregb.lib +276 -0
  297. sage_wheels/share/singular/LIB/control.lib +1636 -0
  298. sage_wheels/share/singular/LIB/crypto.lib +3795 -0
  299. sage_wheels/share/singular/LIB/curveInv.lib +667 -0
  300. sage_wheels/share/singular/LIB/curvepar.lib +1817 -0
  301. sage_wheels/share/singular/LIB/customstd.lib +100 -0
  302. sage_wheels/share/singular/LIB/deRham.lib +5979 -0
  303. sage_wheels/share/singular/LIB/decodegb.lib +2134 -0
  304. sage_wheels/share/singular/LIB/decomp.lib +1655 -0
  305. sage_wheels/share/singular/LIB/deflation.lib +872 -0
  306. sage_wheels/share/singular/LIB/deform.lib +925 -0
  307. sage_wheels/share/singular/LIB/difform.lib +3055 -0
  308. sage_wheels/share/singular/LIB/divisors.lib +750 -0
  309. sage_wheels/share/singular/LIB/dmod.lib +5817 -0
  310. sage_wheels/share/singular/LIB/dmodapp.lib +3269 -0
  311. sage_wheels/share/singular/LIB/dmodideal.lib +1211 -0
  312. sage_wheels/share/singular/LIB/dmodloc.lib +2645 -0
  313. sage_wheels/share/singular/LIB/dmodvar.lib +818 -0
  314. sage_wheels/share/singular/LIB/dummy.lib +17 -0
  315. sage_wheels/share/singular/LIB/elim.lib +1009 -0
  316. sage_wheels/share/singular/LIB/ellipticcovers.lib +548 -0
  317. sage_wheels/share/singular/LIB/enumpoints.lib +146 -0
  318. sage_wheels/share/singular/LIB/equising.lib +2127 -0
  319. sage_wheels/share/singular/LIB/ffmodstd.lib +2384 -0
  320. sage_wheels/share/singular/LIB/ffsolve.lib +1289 -0
  321. sage_wheels/share/singular/LIB/findifs.lib +778 -0
  322. sage_wheels/share/singular/LIB/finitediff.lib +1768 -0
  323. sage_wheels/share/singular/LIB/finvar.lib +7989 -0
  324. sage_wheels/share/singular/LIB/fpadim.lib +2429 -0
  325. sage_wheels/share/singular/LIB/fpalgebras.lib +1666 -0
  326. sage_wheels/share/singular/LIB/fpaprops.lib +1462 -0
  327. sage_wheels/share/singular/LIB/freegb.lib +3853 -0
  328. sage_wheels/share/singular/LIB/general.lib +1350 -0
  329. sage_wheels/share/singular/LIB/gfan.lib +1768 -0
  330. sage_wheels/share/singular/LIB/gitfan.lib +3130 -0
  331. sage_wheels/share/singular/LIB/gkdim.lib +99 -0
  332. sage_wheels/share/singular/LIB/gmspoly.lib +589 -0
  333. sage_wheels/share/singular/LIB/gmssing.lib +1739 -0
  334. sage_wheels/share/singular/LIB/goettsche.lib +909 -0
  335. sage_wheels/share/singular/LIB/graal.lib +1366 -0
  336. sage_wheels/share/singular/LIB/gradedModules.lib +2541 -0
  337. sage_wheels/share/singular/LIB/graphics.lib +360 -0
  338. sage_wheels/share/singular/LIB/grobcov.lib +7706 -0
  339. sage_wheels/share/singular/LIB/groups.lib +1123 -0
  340. sage_wheels/share/singular/LIB/grwalk.lib +507 -0
  341. sage_wheels/share/singular/LIB/hdepth.lib +194 -0
  342. sage_wheels/share/singular/LIB/help.cnf +57 -0
  343. sage_wheels/share/singular/LIB/hess.lib +1946 -0
  344. sage_wheels/share/singular/LIB/hnoether.lib +4292 -0
  345. sage_wheels/share/singular/LIB/hodge.lib +400 -0
  346. sage_wheels/share/singular/LIB/homolog.lib +1965 -0
  347. sage_wheels/share/singular/LIB/hyperel.lib +975 -0
  348. sage_wheels/share/singular/LIB/inout.lib +679 -0
  349. sage_wheels/share/singular/LIB/integralbasis.lib +6224 -0
  350. sage_wheels/share/singular/LIB/interval.lib +1418 -0
  351. sage_wheels/share/singular/LIB/intprog.lib +778 -0
  352. sage_wheels/share/singular/LIB/invar.lib +443 -0
  353. sage_wheels/share/singular/LIB/involut.lib +980 -0
  354. sage_wheels/share/singular/LIB/jacobson.lib +1215 -0
  355. sage_wheels/share/singular/LIB/kskernel.lib +534 -0
  356. sage_wheels/share/singular/LIB/latex.lib +3146 -0
  357. sage_wheels/share/singular/LIB/lejeune.lib +651 -0
  358. sage_wheels/share/singular/LIB/linalg.lib +2040 -0
  359. sage_wheels/share/singular/LIB/locnormal.lib +212 -0
  360. sage_wheels/share/singular/LIB/lrcalc.lib +526 -0
  361. sage_wheels/share/singular/LIB/makedbm.lib +294 -0
  362. sage_wheels/share/singular/LIB/mathml.lib +813 -0
  363. sage_wheels/share/singular/LIB/matrix.lib +1372 -0
  364. sage_wheels/share/singular/LIB/maxlike.lib +1132 -0
  365. sage_wheels/share/singular/LIB/methods.lib +212 -0
  366. sage_wheels/share/singular/LIB/moddiq.lib +322 -0
  367. sage_wheels/share/singular/LIB/modfinduni.lib +181 -0
  368. sage_wheels/share/singular/LIB/modnormal.lib +218 -0
  369. sage_wheels/share/singular/LIB/modprimdec.lib +1278 -0
  370. sage_wheels/share/singular/LIB/modquotient.lib +269 -0
  371. sage_wheels/share/singular/LIB/modstd.lib +1024 -0
  372. sage_wheels/share/singular/LIB/modular.lib +545 -0
  373. sage_wheels/share/singular/LIB/modules.lib +2561 -0
  374. sage_wheels/share/singular/LIB/modwalk.lib +609 -0
  375. sage_wheels/share/singular/LIB/mondromy.lib +1016 -0
  376. sage_wheels/share/singular/LIB/monomialideal.lib +3851 -0
  377. sage_wheels/share/singular/LIB/mprimdec.lib +2353 -0
  378. sage_wheels/share/singular/LIB/mregular.lib +1863 -0
  379. sage_wheels/share/singular/LIB/multigrading.lib +5629 -0
  380. sage_wheels/share/singular/LIB/ncHilb.lib +777 -0
  381. sage_wheels/share/singular/LIB/ncModslimgb.lib +791 -0
  382. sage_wheels/share/singular/LIB/ncalg.lib +16311 -0
  383. sage_wheels/share/singular/LIB/ncall.lib +31 -0
  384. sage_wheels/share/singular/LIB/ncdecomp.lib +468 -0
  385. sage_wheels/share/singular/LIB/ncfactor.lib +13371 -0
  386. sage_wheels/share/singular/LIB/ncfrac.lib +1023 -0
  387. sage_wheels/share/singular/LIB/nchilbert.lib +448 -0
  388. sage_wheels/share/singular/LIB/nchomolog.lib +759 -0
  389. sage_wheels/share/singular/LIB/ncloc.lib +361 -0
  390. sage_wheels/share/singular/LIB/ncpreim.lib +795 -0
  391. sage_wheels/share/singular/LIB/ncrat.lib +2849 -0
  392. sage_wheels/share/singular/LIB/nctools.lib +1887 -0
  393. sage_wheels/share/singular/LIB/nets.lib +1456 -0
  394. sage_wheels/share/singular/LIB/nfmodstd.lib +1000 -0
  395. sage_wheels/share/singular/LIB/nfmodsyz.lib +732 -0
  396. sage_wheels/share/singular/LIB/noether.lib +1106 -0
  397. sage_wheels/share/singular/LIB/normal.lib +8700 -0
  398. sage_wheels/share/singular/LIB/normaliz.lib +2226 -0
  399. sage_wheels/share/singular/LIB/ntsolve.lib +362 -0
  400. sage_wheels/share/singular/LIB/numerAlg.lib +560 -0
  401. sage_wheels/share/singular/LIB/numerDecom.lib +2261 -0
  402. sage_wheels/share/singular/LIB/olga.lib +1933 -0
  403. sage_wheels/share/singular/LIB/orbitparam.lib +351 -0
  404. sage_wheels/share/singular/LIB/parallel.lib +319 -0
  405. sage_wheels/share/singular/LIB/paraplanecurves.lib +3110 -0
  406. sage_wheels/share/singular/LIB/perron.lib +202 -0
  407. sage_wheels/share/singular/LIB/pfd.lib +2223 -0
  408. sage_wheels/share/singular/LIB/phindex.lib +642 -0
  409. sage_wheels/share/singular/LIB/pointid.lib +673 -0
  410. sage_wheels/share/singular/LIB/polybori.lib +1430 -0
  411. sage_wheels/share/singular/LIB/polyclass.lib +525 -0
  412. sage_wheels/share/singular/LIB/polylib.lib +1174 -0
  413. sage_wheels/share/singular/LIB/polymake.lib +1902 -0
  414. sage_wheels/share/singular/LIB/presolve.lib +1533 -0
  415. sage_wheels/share/singular/LIB/primdec.lib +9576 -0
  416. sage_wheels/share/singular/LIB/primdecint.lib +1782 -0
  417. sage_wheels/share/singular/LIB/primitiv.lib +401 -0
  418. sage_wheels/share/singular/LIB/puiseuxexpansions.lib +1631 -0
  419. sage_wheels/share/singular/LIB/purityfiltration.lib +960 -0
  420. sage_wheels/share/singular/LIB/qhmoduli.lib +1561 -0
  421. sage_wheels/share/singular/LIB/qmatrix.lib +293 -0
  422. sage_wheels/share/singular/LIB/random.lib +455 -0
  423. sage_wheels/share/singular/LIB/ratgb.lib +489 -0
  424. sage_wheels/share/singular/LIB/realclassify.lib +5759 -0
  425. sage_wheels/share/singular/LIB/realizationMatroids.lib +772 -0
  426. sage_wheels/share/singular/LIB/realrad.lib +1197 -0
  427. sage_wheels/share/singular/LIB/recover.lib +2628 -0
  428. sage_wheels/share/singular/LIB/redcgs.lib +3984 -0
  429. sage_wheels/share/singular/LIB/reesclos.lib +465 -0
  430. sage_wheels/share/singular/LIB/resbinomial.lib +2802 -0
  431. sage_wheels/share/singular/LIB/resgraph.lib +789 -0
  432. sage_wheels/share/singular/LIB/resjung.lib +820 -0
  433. sage_wheels/share/singular/LIB/resolve.lib +5110 -0
  434. sage_wheels/share/singular/LIB/resources.lib +170 -0
  435. sage_wheels/share/singular/LIB/reszeta.lib +5473 -0
  436. sage_wheels/share/singular/LIB/ring.lib +1328 -0
  437. sage_wheels/share/singular/LIB/ringgb.lib +343 -0
  438. sage_wheels/share/singular/LIB/rinvar.lib +1153 -0
  439. sage_wheels/share/singular/LIB/rootisolation.lib +1481 -0
  440. sage_wheels/share/singular/LIB/rootsmr.lib +709 -0
  441. sage_wheels/share/singular/LIB/rootsur.lib +886 -0
  442. sage_wheels/share/singular/LIB/rstandard.lib +607 -0
  443. sage_wheels/share/singular/LIB/rwalk.lib +336 -0
  444. sage_wheels/share/singular/LIB/sagbi.lib +1353 -0
  445. sage_wheels/share/singular/LIB/sagbiNormaliz.lib +1622 -0
  446. sage_wheels/share/singular/LIB/sagbiNormaliz0.lib +1498 -0
  447. sage_wheels/share/singular/LIB/sagbigrob.lib +449 -0
  448. sage_wheels/share/singular/LIB/schreyer.lib +321 -0
  449. sage_wheels/share/singular/LIB/schubert.lib +2551 -0
  450. sage_wheels/share/singular/LIB/sets.lib +524 -0
  451. sage_wheels/share/singular/LIB/sheafcoh.lib +1663 -0
  452. sage_wheels/share/singular/LIB/signcond.lib +437 -0
  453. sage_wheels/share/singular/LIB/sing.lib +1094 -0
  454. sage_wheels/share/singular/LIB/sing4ti2.lib +419 -0
  455. sage_wheels/share/singular/LIB/solve.lib +2243 -0
  456. sage_wheels/share/singular/LIB/spcurve.lib +1077 -0
  457. sage_wheels/share/singular/LIB/spectrum.lib +62 -0
  458. sage_wheels/share/singular/LIB/sresext.lib +757 -0
  459. sage_wheels/share/singular/LIB/ssi.lib +143 -0
  460. sage_wheels/share/singular/LIB/standard.lib +2769 -0
  461. sage_wheels/share/singular/LIB/stanleyreisner.lib +473 -0
  462. sage_wheels/share/singular/LIB/stdmodule.lib +547 -0
  463. sage_wheels/share/singular/LIB/stratify.lib +1070 -0
  464. sage_wheels/share/singular/LIB/surf.lib +506 -0
  465. sage_wheels/share/singular/LIB/surf_jupyter.lib +223 -0
  466. sage_wheels/share/singular/LIB/surfacesignature.lib +522 -0
  467. sage_wheels/share/singular/LIB/surfex.lib +1462 -0
  468. sage_wheels/share/singular/LIB/swalk.lib +877 -0
  469. sage_wheels/share/singular/LIB/symodstd.lib +1570 -0
  470. sage_wheels/share/singular/LIB/systhreads.lib +74 -0
  471. sage_wheels/share/singular/LIB/tasks.lib +1324 -0
  472. sage_wheels/share/singular/LIB/tateProdCplxNegGrad.lib +2412 -0
  473. sage_wheels/share/singular/LIB/teachstd.lib +858 -0
  474. sage_wheels/share/singular/LIB/template.lib +116 -0
  475. sage_wheels/share/singular/LIB/toric.lib +1119 -0
  476. sage_wheels/share/singular/LIB/transformation.lib +116 -0
  477. sage_wheels/share/singular/LIB/triang.lib +1197 -0
  478. sage_wheels/share/singular/LIB/tropical.lib +8741 -0
  479. sage_wheels/share/singular/LIB/tropicalEllipticCovers.lib +2922 -0
  480. sage_wheels/share/singular/LIB/tropicalNewton.lib +1128 -0
  481. sage_wheels/share/singular/LIB/tst.lib +1108 -0
  482. sage_wheels/share/singular/LIB/weierstr.lib +241 -0
  483. sage_wheels/share/singular/LIB/zeroset.lib +1478 -0
  484. sage_wheels/share/singular/emacs/.emacs-general +184 -0
  485. sage_wheels/share/singular/emacs/.emacs-singular +234 -0
  486. sage_wheels/share/singular/emacs/COPYING +44 -0
  487. sage_wheels/share/singular/emacs/cmd-cmpl.el +241 -0
  488. sage_wheels/share/singular/emacs/ex-cmpl.el +1681 -0
  489. sage_wheels/share/singular/emacs/hlp-cmpl.el +4318 -0
  490. sage_wheels/share/singular/emacs/lib-cmpl.el +179 -0
  491. sage_wheels/share/singular/emacs/singular.el +4273 -0
  492. sage_wheels/share/singular/emacs/singular.xpm +39 -0
  493. sage_wheels/share/singular/singular.idx +5002 -0
@@ -0,0 +1,4273 @@
1
+ ;;; singular.el --- Emacs support for Computer Algebra System Singular
2
+
3
+
4
+ ;;; Commentary:
5
+
6
+
7
+ ;;; Code:
8
+
9
+ ;;{{{ Style and coding conventions
10
+
11
+ ;; Style and coding conventions:
12
+ ;;
13
+ ;; - "Singular" is written with an upper-case `S' in comments, doc
14
+ ;; strings, and messages. As part of symbols, it is written with
15
+ ;; a lower-case `s'.
16
+ ;; - When referring to the Singular interactive mode, do it in that
17
+ ;; wording. Use the notation `singular-interactive-mode' only when
18
+ ;; really referring to the lisp object.
19
+ ;; - use a `fill-column' of 75 for doc strings and comments
20
+ ;; - mark incomplete doc strings or code with `NOT READY' optionally
21
+ ;; followed by an explanation what exactly is missing
22
+ ;;
23
+ ;; - use foldings to structure the source code but try not to exceed a
24
+ ;; maximum depth of two foldings
25
+ ;; - use lowercase folding titles except for first word
26
+ ;; - folding-marks are `;;{{{' and `;;}}}' resp., for sake of standard
27
+ ;; conformity
28
+ ;; - use the foldings to modularize code. That is, each folding should be,
29
+ ;; as far as possible, self-content. Define a function `singular-*-init'
30
+ ;; in the folding to do the initialization of the module contained in
31
+ ;; that folding. Call that function from `singular-interactive-mode',
32
+ ;; for example, instead of initializing the module directly from
33
+ ;; `singular-interactive-mode'. Look at the code how it is done for the
34
+ ;; simple section or for the folding stuff.
35
+ ;;
36
+ ;; - use `singular' as prefix for all global symbols
37
+ ;; - use `singular-debug' as prefix for all global symbols concerning
38
+ ;; debugging.
39
+ ;; - use, whenever possible without names becoming too clumsy, some unique
40
+ ;; prefix inside a folding
41
+ ;;
42
+ ;; - mark dependencies on Emacs flavor/version with a comment of the form
43
+ ;; `;; Emacs[ <version> ]' resp.
44
+ ;; `;; XEmacs[ <version> ][ <nasty comment> ]'
45
+ ;; specified in that order, if possible
46
+ ;; - use a `cond' statement to execute Emacs flavor/version-dependent code,
47
+ ;; not `if'. This is to make such checks more extensible.
48
+ ;; - try to define different functions for different flavors/version and
49
+ ;; use `singular-fset' at library-loading time to set the function you
50
+ ;; really need. If the function is named `singular-<basename>', the
51
+ ;; flavor/version-dependent functions should be named
52
+ ;; `singular-<flavor>[-<version>]-<basename>'.
53
+ ;;
54
+ ;; - use `singular-debug' for debugging output/actions
55
+ ;; - to switch between buffer and process names, use the functions
56
+ ;; `singular-process-name-to-buffer-name' and
57
+ ;; `singular-buffer-name-to-process-name'
58
+ ;; - call the function `singular-keep-region-active' as last statement in
59
+ ;; an interactive function that should keep the region active (for
60
+ ;; example, in functions that move the point). This is necessary to keep
61
+ ;; XEmacs' zmacs regions active.
62
+ ;; - to get the process of the current buffer, use `singular-process'. To
63
+ ;; get the current process mark, use `singular-process-mark'. Both
64
+ ;; functions check whether Singular is alive and throw an error if not,
65
+ ;; so you do not have to care about that yourself. If you do not want an
66
+ ;; error specify non-nil argument NO-ERROR. But use them anyway.
67
+ ;; - we assume that the buffer is *not* read-only
68
+ ;; - use `=' instead of `eq' when comparing buffer locations. Even if you
69
+ ;; are sure that both operands are integers.
70
+
71
+ ;;}}}
72
+
73
+ ;;{{{ Code common to both modes
74
+ ;;{{{ Customizing
75
+ (defgroup singular nil
76
+ "Emacs interface to Singular.
77
+ By now, the Emacs interface to Singular consists of Singular interactive
78
+ mode only. Singular interactive mode provides a convenient front end to
79
+ interactive Singular sessions running inside Emacs.
80
+ In far future maybe there will be a mode for editing Singular source code
81
+ such as libraries or procedures."
82
+ :group 'external)
83
+
84
+ (defgroup singular-faces nil
85
+ "Faces in Singular mode and Singular interactive mode."
86
+ :group 'faces
87
+ :group 'singular-interactive)
88
+ ;;}}}
89
+
90
+ ;;{{{ Debugging stuff
91
+ (defvar singular-debug nil
92
+ "List of modes to debug or t to debug all modes.
93
+ Currently, the following modes are supported:
94
+ `interactive',
95
+ `interactive-filter'.")
96
+
97
+ (defun singular-debug-format (string)
98
+ "Return STRING in a nicer format."
99
+ (save-match-data
100
+ (while (string-match "\n" string)
101
+ (setq string (replace-match "^J" nil nil string)))
102
+
103
+ (if (> (length string) 16)
104
+ (concat "<" (substring string 0 7) ">...<" (substring string -8) ">")
105
+ (concat "<" string ">"))))
106
+
107
+ (defmacro singular-debug (mode form &optional else-form)
108
+ "Major debugging hook for singular.el.
109
+ Evaluates FORM if `singular-debug' equals t or if MODE is an element
110
+ of `singular-debug', otherwise ELSE-FORM."
111
+ `(if (or (eq singular-debug t)
112
+ (memq ,mode singular-debug))
113
+ ,form
114
+ ,else-form))
115
+ ;;}}}
116
+
117
+ ;;{{{ Determining version
118
+ (defvar singular-emacs-flavor nil
119
+ "A symbol describing the current Emacs.
120
+ Currently, only Emacs \(`emacs') and XEmacs \(`xemacs') are supported.")
121
+
122
+ (defvar singular-emacs-major-version nil
123
+ "An integer describing the major version of the current emacs.")
124
+
125
+ (defvar singular-emacs-minor-version nil
126
+ "An integer describing the minor version of the current emacs.")
127
+
128
+ (defun singular-fset (real-function emacs-function xemacs-function)
129
+ "Set REAL-FUNCTION to one of the functions, in dependency on Emacs flavor and version.
130
+ Sets REAL-FUNCTION to XEMACS-FUNCTION if `singular-emacs-flavor' is
131
+ `xemacs', otherwise sets REAL-FUNCTION to EMACS-FUNCTION.
132
+
133
+ This is not as common as it would be desirable. But it is sufficient so
134
+ far."
135
+ (cond
136
+ ;; XEmacs
137
+ ((eq singular-emacs-flavor 'xemacs)
138
+ (fset real-function xemacs-function))
139
+ ;; Emacs
140
+ (t
141
+ (fset real-function emacs-function))))
142
+
143
+ (defun singular-set-version ()
144
+ "Determine flavor, major version, and minor version of current emacs.
145
+ singular.el is guaranteed to run on Emacs 20.3 and XEmacs 20.3.
146
+ It should run on newer version and on slightly older ones, too.
147
+
148
+ This function is called exactly once when singular.el is loaded."
149
+ ;; get major and minor versions first
150
+ (if (and (boundp 'emacs-major-version)
151
+ (boundp 'emacs-minor-version))
152
+ (setq singular-emacs-major-version emacs-major-version
153
+ singular-emacs-minor-version emacs-minor-version)
154
+ (with-output-to-temp-buffer "*singular warnings*"
155
+ (princ
156
+ "You seem to have quite an old Emacs or XEmacs version. Some of the
157
+ features from singular.el will not work properly. Consider upgrading to a
158
+ more recent version of Emacs or XEmacs. singular.el is guaranteed to run
159
+ on Emacs 20.3 and XEmacs 20.3."))
160
+ ;; assume the oldest version we support
161
+ (setq singular-emacs-major-version 20
162
+ singular-emacs-minor-version 3))
163
+
164
+ ;; get flavor
165
+ (if (string-match "XEmacs\\|Lucid" emacs-version)
166
+ (setq singular-emacs-flavor 'xemacs)
167
+ (setq singular-emacs-flavor 'emacs)))
168
+
169
+ (singular-set-version)
170
+ ;;}}}
171
+
172
+ ;;{{{ Syntax table
173
+ (defvar singular-mode-syntax-table nil
174
+ "Syntax table for `singular-interactive-mode' resp. `singular-mode'.")
175
+
176
+ (if singular-mode-syntax-table
177
+ ()
178
+ (setq singular-mode-syntax-table (make-syntax-table))
179
+ ;; stolen from cc-mode.el except for back-tics which are special to Singular
180
+ (modify-syntax-entry ?_ "_" singular-mode-syntax-table)
181
+ (modify-syntax-entry ?\\ "\\" singular-mode-syntax-table)
182
+ (modify-syntax-entry ?+ "." singular-mode-syntax-table)
183
+ (modify-syntax-entry ?- "." singular-mode-syntax-table)
184
+ (modify-syntax-entry ?= "." singular-mode-syntax-table)
185
+ (modify-syntax-entry ?% "." singular-mode-syntax-table)
186
+ (modify-syntax-entry ?< "." singular-mode-syntax-table)
187
+ (modify-syntax-entry ?> "." singular-mode-syntax-table)
188
+ (modify-syntax-entry ?& "." singular-mode-syntax-table)
189
+ (modify-syntax-entry ?| "." singular-mode-syntax-table)
190
+ (modify-syntax-entry ?\' "\"" singular-mode-syntax-table)
191
+ (modify-syntax-entry ?\` "\"" singular-mode-syntax-table)
192
+ ;; block and line-oriented comments
193
+ (cond
194
+ ;; Emacs
195
+ ((eq singular-emacs-flavor 'emacs)
196
+ (modify-syntax-entry ?/ ". 124b" singular-mode-syntax-table)
197
+ (modify-syntax-entry ?* ". 23" singular-mode-syntax-table))
198
+ ;; XEmacs
199
+ (t
200
+ (modify-syntax-entry ?/ ". 1456" singular-mode-syntax-table)
201
+ (modify-syntax-entry ?* ". 23" singular-mode-syntax-table)))
202
+ (modify-syntax-entry ?\n "> b" singular-mode-syntax-table)
203
+ (modify-syntax-entry ?\^m "> b" singular-mode-syntax-table))
204
+
205
+ (defun singular-mode-syntax-table-init ()
206
+ "Initialize syntax table of current buffer.
207
+
208
+ This function is called at mode initialization time."
209
+ (set-syntax-table singular-mode-syntax-table))
210
+ ;;}}}
211
+
212
+ ;;{{{ Miscellaneous
213
+ (defsubst singular-keep-region-active ()
214
+ "Do whatever is necessary to keep the region active in XEmacs.
215
+ Ignore byte-compiler warnings you might see. This is not needed for
216
+ Emacs."
217
+ ;; XEmacs. We do not use the standard way here to test for flavor
218
+ ;; because it is presumably faster with that test on `boundp'.
219
+ (and (boundp 'zmacs-region-stays)
220
+ (setq zmacs-region-stays t)))
221
+ ;;}}}
222
+ ;;}}}
223
+
224
+ ;;{{{ Singular interactive mode
225
+ ;;{{{ Customizing
226
+
227
+ ;; Note:
228
+ ;;
229
+ ;; Some notes on Customize:
230
+ ;;
231
+ ;; - The documentation states that for the `:initialize' option of
232
+ ;; `defcustom' the default value is `custom-initialize-set'. However, in
233
+ ;; the source code of Customize `custom-initialize-reset' is used. So
234
+ ;; better always specify the `:initialize' option explicitly.
235
+ ;; - Customize is bad at setting buffer-local variables or properties.
236
+ ;; This is quite natural since Customize itself uses its own buffer. So
237
+ ;; changing buffer-local variables and properties with Customize is
238
+ ;; possible only at a "Singular-global" level. That is, for all buffers
239
+ ;; currently having Singular interactive mode as major mode. The function
240
+ ;; `singular-map-buffer' helps to do such customization.
241
+ ;; - Important note: Customizable variables are not automatically marked as
242
+ ;; user options. This has to be done as usual by marking them with a '*'
243
+ ;; as first character of the documentation string. Without that, the
244
+ ;; variables are not accessible to, for example, `set-variable'.
245
+ ;;
246
+ ;; Some common customizing patterns:
247
+ ;;
248
+ ;; - How to customize buffer-local properties?
249
+ ;; First, the `defcustom' itself must not set anything buffer-local since
250
+ ;; at time of its definition (most likely) no Singular buffers will be
251
+ ;; around. If there are Singular buffers we do not care about them. But
252
+ ;; anyhow, at definition of the `defcustom' the global default has to be
253
+ ;; set. Hence, the `:initialize' option should be set to
254
+ ;; `custom-initialize-default'.
255
+ ;; The buffer-local initialization has to be done at mode initialization
256
+ ;; time. The global default value should then be used to set the local
257
+ ;; properties.
258
+ ;; At last, the function specified with the `:set' option should set the
259
+ ;; local properties in all Singular buffers to the new, customized value.
260
+ ;; Most likely, the function `singular-map-buffer' may be used for that.
261
+ ;; In addition, the function should, of course, set the global value via
262
+ ;; `set-default'.
263
+ ;; For an example, see `singular-folding-line-move-ignore-folding'.
264
+ ;;
265
+ ;; - How to encapsulate other mode's global variables into Singular
266
+ ;; interactive mode variables?
267
+ ;; Set them always. That is, set them if the `defcustom' is evaluated
268
+ ;; (use `custom-initialize-reset' as `:initial' function) and set them
269
+ ;; when the Singular interactive mode variable is customized (by means
270
+ ;; of an appropriate `:set' function).
271
+ ;; For an example, see `singular-section-face-alist' (which does not
272
+ ;; encapsulate another mode's variable, but Singular interactive mode's
273
+ ;; own variable `singular-simple-sec-clear-type').
274
+
275
+ (defgroup singular-interactive nil
276
+ "Running interactive Singular sessions inside Emacs."
277
+ :group 'singular
278
+ :group 'processes)
279
+
280
+ (defgroup singular-sections-and-foldings nil
281
+ "Sections and foldings in Singular interactive mode."
282
+ :group 'singular-interactive)
283
+
284
+ (defgroup singular-interactive-miscellaneous nil
285
+ "Miscellaneous settings for Singular interactive mode."
286
+ :group 'singular-interactive)
287
+
288
+ (defgroup singular-demo-mode nil
289
+ "Settings concerning Singular demo mode."
290
+ :group 'singular-interactive)
291
+
292
+ (defun singular-map-buffer (func &rest args)
293
+ "Apply FUNC to ARGS in all existing Singular buffers.
294
+ That is, in all buffers having Singular interactive major mode. The
295
+ function is executed in the context of the buffer. This is a must-have for
296
+ the customizing stuff to change buffer-local properties."
297
+ (save-excursion
298
+ (mapcar (function
299
+ (lambda (buffer)
300
+ (set-buffer buffer)
301
+ (if (eq major-mode 'singular-interactive-mode)
302
+ (apply func args))))
303
+ (buffer-list))))
304
+ ;;}}}
305
+
306
+ ;;{{{ Comint
307
+
308
+ ;; Note:
309
+ ;;
310
+ ;; We require Comint, but we really do not use it too much. One may argue
311
+ ;; that this is bad since Comint is a standardized way to communicate with
312
+ ;; external processes. One may argue further that many experienced Emacs
313
+ ;; users are forced now to re-do their Comint customization for Singular
314
+ ;; interactive mode. However, we believe that the intersection between
315
+ ;; experienced Emacs users and users of Singular interactive mode is almost
316
+ ;; empty.
317
+ ;;
318
+ ;; In fact, we used Comint really much in the beginning of this project.
319
+ ;; Later during development it turned at that using Comint's input and
320
+ ;; output processing is to inflexible and not appropriate for Singular
321
+ ;; interactive mode with its input and output sections. So we begun to
322
+ ;; rewrite large portions of Comint to adapt it to our needs. At some
323
+ ;; point it came clear that it would be best to throw out Comint
324
+ ;; all together, would not have been there some auxiliary functions which
325
+ ;; are really useful but annoying to rewrite. These are, for example, the
326
+ ;; command line history functions or the completion stuff offered by
327
+ ;; Comint.
328
+ ;;
329
+ ;; Our policy with regard to these remainders of Comint is: Use the
330
+ ;; functions to bind them to keys, but do not use them internally.
331
+ ;; Encapsulate Comint customization into Singular interactive mode
332
+ ;; customization. In particular, do not take care about Comint settings
333
+ ;; which already may be present, overwrite them. Hide Comint from the
334
+ ;; user.
335
+ ;;
336
+ ;; Here is how exactly we use Comint:
337
+ ;;
338
+ ;; - All variables necessary to use Comint's input ring are properly
339
+ ;; initialized. One may find this in the `History' folding.
340
+ ;; - `comint-prompt-regexp' is initialized since it is used in some
341
+ ;; of the functions regarding input ring handling. Furthermore, its
342
+ ;; initialization enables us to use functions as `comint-bol', etc.
343
+ ;; Initialization is done in the `Skipping and stripping prompts ...'
344
+ ;; folding.
345
+ ;; - We call `comint-mode' as first step in `singular-interactive-mode'.
346
+ ;; Most of the work done there is to initialize the local variables as
347
+ ;; necessary. Besides that, the function does nothing that interferes
348
+ ;; with Singular interactive mode. To be consequent we set
349
+ ;; `comint-mode-hook' temporarily to nil when calling `comint-mode'.
350
+ ;; - In `singular-exec', we use `comint-exec-1' to fire up the process.
351
+ ;; Furthermore, we set `comint-ptyp' there as it is used in the signal
352
+ ;; sending commands of Comint. All that `comint-exec-1' does is that it
353
+ ;; sets up the process environment (it adds or modifies the setting of
354
+ ;; the 'TERM' variable), sets the execution directory, and does some
355
+ ;; magic with the process coding stuff.
356
+ ;; - One more time the most important point: we do *not* use Comint's
357
+ ;; output and input processing. In particular, we do not run any of
358
+ ;; Comint's hooks on input or output. Anyway, we do better, don't we?
359
+
360
+ (require 'comint)
361
+
362
+ (defun singular-comint-init ()
363
+ "Initialize comint stuff for Singular interactive mode.
364
+
365
+ This function is called at mode initialization time."
366
+ (setq comint-completion-addsuffix '("/" . "")))
367
+ ;;}}}
368
+
369
+ ;;{{{ Font-locking
370
+ (defvar singular-font-lock-error-face 'singular-font-lock-error-face
371
+ "Face name to use for Singular errors.")
372
+
373
+ (defvar singular-font-lock-warning-face 'singular-font-lock-warning-face
374
+ "Face name to use for Singular warnings.")
375
+
376
+ (defvar singular-font-lock-prompt-face 'singular-font-lock-prompt-face
377
+ "Face name to use for Singular prompts.")
378
+
379
+ (defface singular-font-lock-error-face
380
+ '((((class color)) (:foreground "Red" :bold t))
381
+ (t (:inverse-video t :bold t)))
382
+ "*Font Lock mode face used to highlight Singular errors."
383
+ :group 'singular-faces)
384
+
385
+ (defface singular-font-lock-warning-face
386
+ '((((class color)) (:foreground "OrangeRed" :bold nil))
387
+ (t (:inverse-video t :bold t)))
388
+ "*Font Lock mode face used to highlight Singular warnings."
389
+ :group 'singular-faces)
390
+
391
+ (defface singular-font-lock-prompt-face
392
+ '((((class color) (background light)) (:foreground "Blue" :bold t))
393
+ (((class color) (background dark)) (:foreground "LightSkyBlue" :bold t))
394
+ (t (:inverse-video t :bold t)))
395
+ "*Font Lock mode face used to highlight Singular prompts."
396
+ :group 'singular-faces)
397
+
398
+ (defconst singular-font-lock-singular-types nil
399
+ "List of Singular types.")
400
+
401
+ (eval-when-compile
402
+ (setq singular-font-lock-singular-types
403
+ '("def" "bigint" "ideal" "int" "intmat" "intvec" "link" "list" "map"
404
+ "matrix" "module" "number" "poly" "proc" "qring" "resolution" "ring"
405
+ "string" "vector")))
406
+
407
+ (defconst singular-interactive-font-lock-keywords-1
408
+ '(
409
+ ("^\\([>.]\\) " 1 singular-font-lock-prompt-face t)
410
+ ("^ [\\?].*" 0 singular-font-lock-error-face t)
411
+ ("^// \\*\\*.*" 0 singular-font-lock-warning-face t)
412
+ )
413
+ "Subdued level highlighting for Singular interactive mode")
414
+
415
+ (defconst singular-interactive-font-lock-keywords-2
416
+ (append
417
+ singular-interactive-font-lock-keywords-1
418
+ (eval-when-compile
419
+ (list
420
+ (cons
421
+ (concat "\\<" (regexp-opt singular-font-lock-singular-types t) "\\>")
422
+ 'font-lock-type-face))))
423
+ "Medium level highlighting for Singular interactive mode")
424
+
425
+ (defconst singular-interactive-font-lock-keywords-3
426
+ (append
427
+ singular-interactive-font-lock-keywords-2
428
+ '(
429
+ ;; note: we use font-lock-reference-face here even Emacs says that
430
+ ;; this face is obsolete and suggests to use font-lock-constant-face,
431
+ ;; since XEmacs20/21 does not know the constant-face but the
432
+ ;; reference-face.
433
+ ("^ [\\?].*`\\(\\sw\\sw+;?\\)`" 1 font-lock-reference-face t)
434
+ ))
435
+ "Gaudy level highlighting for Singular interactive mode.")
436
+
437
+ (defconst singular-interactive-font-lock-keywords singular-interactive-font-lock-keywords-1
438
+ "Default highlighting for Singular interactive mode.")
439
+
440
+ (defconst singular-interactive-font-lock-defaults
441
+ '((singular-interactive-font-lock-keywords
442
+ singular-interactive-font-lock-keywords-1
443
+ singular-interactive-font-lock-keywords-2
444
+ singular-interactive-font-lock-keywords-3)
445
+ ;; KEYWORDS-ONLY (do not fontify strings & comments if non-nil)
446
+ nil
447
+ ;; CASE-FOLD (ignore case if non-nil)
448
+ nil
449
+ ;; SYNTAX-ALIST (add this to Font Lock's syntax table)
450
+ ((?_ . "w"))
451
+ ;; SYNTAX-BEGIN
452
+ singular-section-goto-beginning)
453
+ "Default expressions to highlight in Singular interactive mode.")
454
+
455
+ (defun singular-interactive-font-lock-init ()
456
+ "Initialize Font Lock mode for Singular interactive mode.
457
+
458
+ For XEmacs, this function is called exactly once when singular.el is
459
+ loaded.
460
+ For Emacs, this function is called at mode initialization time."
461
+ (cond
462
+ ;; Emacs
463
+ ((eq singular-emacs-flavor 'emacs)
464
+ (singular-debug 'interactive (message "Setting up Font Lock mode for Emacs"))
465
+ (set (make-local-variable 'font-lock-defaults)
466
+ singular-interactive-font-lock-defaults))
467
+ ;; XEmacs
468
+ ((eq singular-emacs-flavor 'xemacs)
469
+ (singular-debug 'interactive (message "Setting up Font Lock mode for XEmacs"))
470
+ (put 'singular-interactive-mode
471
+ 'font-lock-defaults singular-interactive-font-lock-defaults))))
472
+
473
+ ;; XEmacs Font Lock mode initialization
474
+ (cond
475
+ ;; XEmacs
476
+ ((eq singular-emacs-flavor 'xemacs)
477
+ (singular-interactive-font-lock-init)))
478
+ ;;}}}
479
+
480
+ ;;{{{ Key map
481
+ (defvar singular-interactive-mode-map nil
482
+ "Key map to use in Singular interactive mode.")
483
+
484
+ (if singular-interactive-mode-map
485
+ ()
486
+ ;; create empty keymap first
487
+ (cond
488
+ ;; Emacs
489
+ ((eq singular-emacs-flavor 'emacs)
490
+ (setq singular-interactive-mode-map (make-sparse-keymap)))
491
+ ;; XEmacs
492
+ (t
493
+ (setq singular-interactive-mode-map (make-keymap))
494
+ (set-keymap-name singular-interactive-mode-map
495
+ 'singular-interactive-mode-map)))
496
+
497
+ ;; global settings
498
+ (define-key help-map [?\C-s] 'singular-help)
499
+
500
+ ;; settings for `singular-interactive-map'
501
+ (substitute-key-definition 'beginning-of-line 'singular-beginning-of-line
502
+ singular-interactive-mode-map global-map)
503
+
504
+ (define-key singular-interactive-mode-map "\t" 'singular-dynamic-complete)
505
+ (define-key singular-interactive-mode-map [?\C-m] 'singular-send-or-copy-input)
506
+ (define-key singular-interactive-mode-map [?\C-l] 'singular-recenter)
507
+
508
+ ;; Comint functions
509
+ (define-key singular-interactive-mode-map [?\M-r] 'comint-previous-matching-input)
510
+ (define-key singular-interactive-mode-map [?\M-s] 'comint-next-matching-input)
511
+
512
+ ;; C-c prefix
513
+ (define-key singular-interactive-mode-map [?\C-c ?\C-e] 'singular-example)
514
+ (define-key singular-interactive-mode-map [?\C-c ?\C-t] 'singular-toggle-truncate-lines)
515
+
516
+ (define-key singular-interactive-mode-map [?\C-c ?\C-f] 'singular-folding-toggle-fold-at-point-or-all)
517
+ (define-key singular-interactive-mode-map [?\C-c ?\C-o] 'singular-folding-toggle-fold-latest-output)
518
+ (define-key singular-interactive-mode-map [?\C-c ?\C-w] 'singular-section-kill)
519
+
520
+ (define-key singular-interactive-mode-map [?\C-c ?\C-d] 'singular-demo-load)
521
+ (define-key singular-interactive-mode-map [?\C-c ?\C-l] 'singular-load-library)
522
+ (define-key singular-interactive-mode-map [(control c) (<)] 'singular-load-file)
523
+
524
+ (define-key singular-interactive-mode-map [?\C-c ?\C-r] 'singular-restart)
525
+ (define-key singular-interactive-mode-map [?\C-c ?\$] 'singular-exit-singular)
526
+ (define-key singular-interactive-mode-map [?\C-c ?\C-c] 'singular-control-c))
527
+
528
+ (defun singular-cursor-key-model-set (key-model)
529
+ "Set keys according to KEY-MODEL.
530
+ KEY-MODEL should be one of the valid values of `singular-cursor-key-model'."
531
+ ;; convert symbols to list
532
+ (cond ((eq key-model 'emacs)
533
+ (setq key-model '(cursor cursor history)))
534
+ ((eq key-model 'terminal)
535
+ (setq key-model '(history history cursor))))
536
+
537
+ ;; work through list
538
+ (mapcar (function (lambda (spec)
539
+ (let ((key-description (nth 0 spec))
540
+ (prev-key (nth 1 spec))
541
+ (next-key (nth 2 spec)))
542
+ (cond ((eq key-description 'cursor)
543
+ (define-key singular-interactive-mode-map prev-key 'previous-line)
544
+ (define-key singular-interactive-mode-map next-key 'next-line))
545
+ ((eq key-description 'history)
546
+ (define-key singular-interactive-mode-map prev-key 'comint-previous-input)
547
+ (define-key singular-interactive-mode-map next-key 'comint-next-input))
548
+ (t
549
+ (define-key singular-interactive-mode-map prev-key nil)
550
+ (define-key singular-interactive-mode-map next-key nil))))))
551
+
552
+ ;; here is where list position are mapped to keys
553
+ (list (list (nth 0 key-model) [up] [down])
554
+ (list (nth 1 key-model) [?\C-p] [?\C-n])
555
+ (list (nth 2 key-model) [?\M-p] [?\M-n]))))
556
+
557
+ (defcustom singular-cursor-key-model 'emacs
558
+ "*Keys to use for cursor movement and history access, respectively.
559
+ An experienced Emacs user would prefer setting `singular-cursor-key-model'
560
+ to `emacs'. This means that C-p, C-n, and the cursor keys move the cursor,
561
+ whereas M-p and M-n scroll through the history of Singular commands.
562
+
563
+ On the other hand, an user used to running Singular in a, say, xterm, would
564
+ prefer setting `singular-cursor-key-model' to `terminal'. This means that
565
+ C-p, C-n, and the cursor keys scroll through the history of Singular
566
+ commands, whereas M-p and M-n move the cursor.
567
+
568
+ For those who do not like neither standard setting, there is the
569
+ possibility to set this variable to a list of three elements where
570
+ - the first element specifies the key bindings for the cursor keys,
571
+ - the second element specifies the key bindings for C-p and C-n, and
572
+ - the third element specifies the key bindings for M-p and M-n.
573
+ Each list element should be one of
574
+ - `cursor', meaning that the corresponding keys are bound to cursor movement,
575
+ - `history', meaning that the corresponding keys are bound to history access,
576
+ or
577
+ - nil, meaning that the corresponding keys are not bound at all.
578
+
579
+ Changing this variable has an immediate effect only if one uses
580
+ \\[customize] to do so."
581
+ :type '(choice (const :tag "Emacs-like" emacs)
582
+ (const :tag "Terminal-like" terminal)
583
+ (list :tag "User-defined"
584
+ (choice :format "Cursor keys: %[Value Menu%] %v"
585
+ :value cursor
586
+ (const :tag "Cursor movement" cursor)
587
+ (const :tag "History access" history)
588
+ (const :tag "No binding" nil))
589
+ (choice :format "C-p, C-n: %[Value Menu%] %v"
590
+ :value cursor
591
+ (const :tag "Cursor movement" cursor)
592
+ (const :tag "History access" history)
593
+ (const :tag "No binding" nil))
594
+ (choice :format "M-p, M-n: %[Value Menu%] %v"
595
+ :value history
596
+ (const :tag "Cursor movement" cursor)
597
+ (const :tag "History access" history)
598
+ (const :tag "No binding" nil))))
599
+ :initialize 'custom-initialize-reset
600
+ :set (function
601
+ (lambda (var value)
602
+ (singular-cursor-key-model-set value)
603
+ (set-default var value)))
604
+ :group 'singular-interactive-miscellaneous)
605
+
606
+ (defun singular-interactive-mode-map-init ()
607
+ "Initialize key map for Singular interactive mode.
608
+
609
+ This function is called at mode initialization time."
610
+ (use-local-map singular-interactive-mode-map))
611
+ ;;}}}
612
+
613
+ ;;{{{ Menus and logos
614
+ (defvar singular-interactive-mode-menu-1 nil
615
+ "NOT READY [docu]")
616
+
617
+ (defvar singular-interactive-mode-menu-2 nil
618
+ "NOT READY [docu]")
619
+
620
+ (defconst singular-menu-initial-library-menu
621
+ '(["other..." (singular-load-library t) t])
622
+ "Menu definition for the initial library sub menu.
623
+ This should be a list of vectors.")
624
+
625
+ (defun singular-menu-build-libraries-menu (definition)
626
+ "Given a description of the libraries and their categories, builds up a
627
+ menu definition including submenus which can be given to
628
+ `easy-menu-change'. By side effect sets the variable
629
+ `singular-standard-libraries-alist' to the alist of all library names.
630
+ This alist can be used for completion."
631
+ (let ((menudef ())
632
+ (libs definition)
633
+ elem)
634
+ (while libs
635
+ (setq elem (car libs))
636
+ (if (> (length elem) 1)
637
+ (setq menudef
638
+ (append
639
+ (list
640
+ (append (list (car elem))
641
+ (singular-menu-build-libraries-menu (cdr elem))))
642
+ menudef))
643
+ (setq menudef
644
+ (append (list (vector (car elem)
645
+ (list 'singular-load-library nil
646
+ (car elem))
647
+ t))
648
+ menudef))
649
+ (setq singular-standard-libraries-alist
650
+ (append (list elem) singular-standard-libraries-alist)))
651
+ (setq libs (cdr libs)))
652
+ menudef))
653
+
654
+ (defun singular-menu-install-libraries ()
655
+ "Update the singular command menu with libraries.
656
+ Scans the variable `singular-standard-libraries-with-categories' and builds
657
+ up a menu with submenues for each category in the submenu (\"Commands\"
658
+ \"Libraries\")."
659
+ (singular-debug 'interactive (message "Installing library menu"))
660
+ ;; To be compatible with older versions of singular.el (resp. of lib-cmpl.el)
661
+ ;; we check whether the variable
662
+ ;; `singular-standard-libraries-with-categories' is set. If not, we use the
663
+ ;; value of `singular-standard-libraries-alist' instead.
664
+ (if (not singular-standard-libraries-with-categories)
665
+ (setq singular-standard-libraries-with-categories
666
+ singular-standard-libraries-alist))
667
+ (easy-menu-change '("Commands")
668
+ "Libraries"
669
+ (append
670
+ (singular-menu-build-libraries-menu
671
+ singular-standard-libraries-with-categories)
672
+ (append '("---") singular-menu-initial-library-menu))))
673
+
674
+ (defun singular-menu-init ()
675
+ "Initialize menu stuff for Singular interactive mode.
676
+
677
+ This function is called by `singular-exec'."
678
+ (singular-debug 'interactive (message "Initializing menu stuff"))
679
+ (make-local-variable 'singular-standard-libraries-alist)
680
+ (make-local-variable 'singular-standard-libraries-with-categories))
681
+
682
+ (defun singular-menu-deinstall-libraries ()
683
+ "Initialize library submenu from singular command menu.
684
+ Sets the submenu (\"Commands\" \"Libraries\") to the value of
685
+ `singular-menu-initial-library-menu'."
686
+ (singular-debug 'interactive
687
+ (message "Removing libraries from menu"))
688
+ (easy-menu-change '("Commands") "Libraries" singular-menu-initial-library-menu))
689
+
690
+ ;; For some reasons emacs inserts new menus in the oppsite order.
691
+ ;; Defining menu-2 prior to menu-1 will result in the following menu:
692
+ ;; Singular Commands
693
+ ;; That's what we want. So DO NOT exchange both (or ..) statements!
694
+ (or singular-interactive-mode-menu-2
695
+ (easy-menu-define
696
+ singular-interactive-mode-menu-2
697
+ singular-interactive-mode-map ""
698
+ (list
699
+ "Commands"
700
+ ["Fold/Unfold Latest Output" singular-folding-toggle-fold-latest-output t]
701
+ ["Fold/Unfold At Point" singular-folding-toggle-fold-at-point-or-all t]
702
+ ["Fold All Output" singular-folding-fold-all-output t]
703
+ ["Unfold All Output" singular-folding-unfold-all-output t]
704
+ "---"
705
+ ["Truncate Lines" singular-toggle-truncate-lines
706
+ :style toggle :selected truncate-lines]
707
+ "--"
708
+ (append
709
+ '("Libraries")
710
+ singular-menu-initial-library-menu)
711
+ ["Load File..." singular-load-file t]
712
+ "---"
713
+ ["Load Demo..." singular-demo-load (or singular-demo-exit-on-load
714
+ (not singular-demo-mode))]
715
+ ["Exit Demo" singular-demo-exit singular-demo-mode]
716
+ )))
717
+
718
+ (or singular-interactive-mode-menu-1
719
+ (easy-menu-define singular-interactive-mode-menu-1
720
+ singular-interactive-mode-map ""
721
+ '("Singular"
722
+ ["Start Default" singular t]
723
+ ["Start..." singular-other t]
724
+ ["Restart" singular-restart t]
725
+ "---"
726
+ ["Interrupt" singular-control-c t]
727
+ ["Exit" singular-exit-singular t]
728
+ "---"
729
+ ["Preferences" (customize-group 'singular-interactive) t]
730
+ ["Singular Example" singular-example t]
731
+ ["Singular Help" singular-help t])))
732
+
733
+ (defun customize-singular-interactive ()
734
+ (interactive)
735
+ (customize-group 'singular-interactive))
736
+
737
+ (defun singular-interactive-mode-menu-init ()
738
+ "Initialize menus for Singular interactive mode.
739
+
740
+ This function is called at mode initialization time."
741
+ ;; Remove any potential menu which comint-mode might has added.
742
+ (cond
743
+ ;; Emacs
744
+ ((eq singular-emacs-flavor 'emacs)
745
+ ;; Note that easy-menu-remove is a nop in emacs.
746
+ (define-key comint-mode-map [menu-bar signals] nil)
747
+ (define-key comint-mode-map [menu-bar inout] nil)
748
+ (define-key comint-mode-map [menu-bar completion] nil))
749
+ ;;Xemacs
750
+ (t
751
+ (easy-menu-remove '("Singular"))
752
+ (easy-menu-remove '("Comint1")) ; XEmacs 20
753
+ (easy-menu-remove '("Comint2")) ; XEmacs 20
754
+ (easy-menu-remove '("History")) ; XEmacs 20
755
+ (easy-menu-remove '("Complete")) ; XEmacs 21
756
+ (easy-menu-remove '("In/Out")) ; XEmacs 21
757
+ (easy-menu-remove '("Signals")))) ; XEmacs 21
758
+
759
+ ;; Note: easy-menu-add is not necessary in emacs, since the menu
760
+ ;; is added automatically with the keymap.
761
+ ;; See help on `easy-menu-add'
762
+ (easy-menu-add singular-interactive-mode-menu-1)
763
+ (easy-menu-add singular-interactive-mode-menu-2))
764
+ ;;}}}
765
+
766
+ ;;{{{ Skipping and stripping prompts and whitespace and other things
767
+
768
+ ;; Note:
769
+ ;;
770
+ ;; Most of these functions handle prompt recognition, prompt skipping,
771
+ ;; prompt stripping, and so on. It turned out that it would be very
772
+ ;; inefficient to use one generic regular expression to do so. Hence, we
773
+ ;; decided to hardcode the prompt skipping and stripping in an API. If one
774
+ ;; decides to use some other prompt the whole API has to be changed.
775
+ ;; Hopefully, the Singular prompt does not change in near future ...
776
+ ;;
777
+ ;; In addition to the API, the Comint mode variable `comint-mode-regexp' is
778
+ ;; set on initialization of Singular interactive mode. Singular
779
+ ;; interactive mode seems to do quite well without that, but for safety the
780
+ ;; variable is set nonetheless.
781
+
782
+ (defsubst singular-prompt-skip-forward ()
783
+ "Skip forward over prompts."
784
+ (if (looking-at "\\([>.] \\)+")
785
+ (goto-char (match-end 0))))
786
+
787
+ (defsubst singular-prompt-skip-backward ()
788
+ "Skip backward over prompts."
789
+ ;; is that really the simplest and fastest method? The problem is that
790
+ ;; `re-search-backward' is not greedy so on an regexp as "\\([>.] \\)+"
791
+ ;; it stops right after the first occurrence of the sub-expression.
792
+ ;; Anyway, the `(- (point) 2)' expression is OK, even at bob.
793
+ (while (re-search-backward "[>.] " (- (point) 2) t)))
794
+
795
+ (defun singular-prompt-remove-string (string)
796
+ "Remove all prompts from STRING."
797
+ (while (string-match "^\\([>.] \\)+" string)
798
+ (setq string (replace-match "" t t string)))
799
+ string)
800
+
801
+ (defun singular-prompt-remove-region (beg end)
802
+ "Remove all superfluous prompts from region between BEG and END.
803
+ Removes only sequences of prompts that start at beginning of line. Removes
804
+ all but the last prompt of a sequence if that sequence ends at END,
805
+ otherwise removes all prompts.
806
+ The region between BEG and END should be accessible. BEG should be less
807
+ than or equal to END.
808
+ Leaves point at the position of the last sequence of prompts which has been
809
+ deleted or at BEG if nothing has been deleted."
810
+ ;; we cannot exclude this case, I think
811
+ (if (/= beg end)
812
+ ;; that's a nice trick to keep the last prompt if it ends at END: we
813
+ ;; set `(1- END)' as search limit. Since BEG /= END there can be no
814
+ ;; problems with the `1-'.
815
+ (let ((end (copy-marker (1- end))))
816
+ (goto-char beg)
817
+ (while (re-search-forward "^\\([>.] \\)+" end t)
818
+ (delete-region (match-beginning 0) (match-end 0)))
819
+ (set-marker end nil))))
820
+
821
+ (defun singular-prompt-remove-filter (beg end simple-sec-start)
822
+ "Remove all superfluous prompts from text inserted into buffer."
823
+ (cond (;; if a new simple section has been created remove all
824
+ ;; prompts from that simple section
825
+ simple-sec-start
826
+ (singular-prompt-remove-region simple-sec-start end))
827
+ (;; if no simple section has been created check whether maybe the
828
+ ;; region between beg and end consists of prompts only. This in
829
+ ;; case that the user issued a command that did not output any
830
+ ;; text.
831
+ (and (goto-char beg)
832
+ (re-search-forward "\\([>.] \\)+" end t)
833
+ (= (match-end 0) end))
834
+ (singular-prompt-remove-region (progn (beginning-of-line) (point))
835
+ end))))
836
+
837
+ (defun singular-white-space-strip (string &optional trailing leading)
838
+ "Strip off trailing or leading whitespace from STRING.
839
+ Strips off trailing whitespace if optional argument TRAILING is non-nil.
840
+ Strips off leading whitespace if optional argument LEADING is non-nil."
841
+ (let (beg end)
842
+ (and leading
843
+ (string-match "\\`[ \t\n\r\f]+" string)
844
+ (setq beg (match-end 0)))
845
+ (and trailing
846
+ (string-match "[ \t\n\r\f]+\\'" string)
847
+ (setq end (match-beginning 0)))
848
+ (if (or beg end)
849
+ (substring string (or beg 0) (or end (length string)))
850
+ string)))
851
+
852
+ (defconst singular-comint-prompt-regexp "^\\([>.] \\)+"
853
+ "Regexp to match prompt patterns in Singular.
854
+ This variable is used to initialize `comint-prompt-regexp' when Singular
855
+ interactive mode starts up. It is not used in Singular interactive mode
856
+ itself! One should refer to the source code for more information on how to
857
+ adapt Singular interactive mode to some other prompt.")
858
+
859
+ (defun singular-prompt-init ()
860
+ "Initialize prompt skipping and stripping for Singular interactive mode.
861
+
862
+ This function is called at mode initialization time."
863
+ ;; remove superfluous prompts in singular output
864
+ (add-hook 'singular-post-output-filter-functions 'singular-prompt-remove-filter nil t)
865
+
866
+ ;; some relict from Comint mode
867
+ (setq comint-prompt-regexp singular-comint-prompt-regexp))
868
+ ;; required to use prompt-regexp
869
+ (setq comint-use-prompt-regexp t)
870
+ ;;}}}
871
+
872
+ ;;{{{ Miscellaneous
873
+
874
+ ;; Note:
875
+ ;;
876
+ ;; We assume a one-to-one correspondence between Singular buffers and
877
+ ;; Singular processes. We always have (equal buffer-name (concat "*"
878
+ ;; process-name "*")).
879
+
880
+ (defsubst singular-buffer-name-to-process-name (buffer-name)
881
+ "Create the process name for BUFFER-NAME.
882
+ The process name is the buffer name with surrounding `*' stripped off."
883
+ (substring buffer-name 1 -1))
884
+
885
+ (defsubst singular-process-name-to-buffer-name (process-name)
886
+ "Create the buffer name for PROCESS-NAME.
887
+ The buffer name is the process name with surrounding `*'."
888
+ (concat "*" process-name "*"))
889
+
890
+ (defsubst singular-run-hook-with-arg-and-value (hook value)
891
+ "Call functions on HOOK.
892
+ Provides argument VALUE to the functions. If a function returns a non-nil
893
+ value it replaces VALUE as new argument to the remaining functions.
894
+ Returns final VALUE."
895
+ (while hook
896
+ (setq value (or (funcall (car hook) value) value)
897
+ hook (cdr hook)))
898
+ value)
899
+
900
+ (defsubst singular-process (&optional no-error)
901
+ "Return process of current buffer.
902
+ If no process is active this function silently returns nil if optional
903
+ argument NO-ERROR is non-nil, otherwise it throws an error."
904
+ (cond ((get-buffer-process (current-buffer)))
905
+ (no-error nil)
906
+ (t (error "No Singular running in this buffer"))))
907
+
908
+ (defsubst singular-process-mark (&optional no-error)
909
+ "Return process mark of current buffer.
910
+ If no process is active this function silently returns nil if optional
911
+ argument NO-ERROR is non-nil, otherwise it throws an error."
912
+ (let ((process (singular-process no-error)))
913
+ (and process
914
+ (process-mark process))))
915
+
916
+ (defun singular-time-stamp-difference (new-time-stamp old-time-stamp)
917
+ "Return the number of seconds between NEW-TIME-STAMP and OLD-TIME-STAMP.
918
+ Both NEW-TIME-STAMP and OLD-TIME-STAMP should be in the format
919
+ that is returned, for example, by `current-time'.
920
+ Does not return a difference larger than 2^17 seconds."
921
+ (let ((high-difference (min 1 (- (car new-time-stamp) (car old-time-stamp))))
922
+ (low-difference (- (cadr new-time-stamp) (cadr old-time-stamp))))
923
+ (+ (* high-difference 131072) low-difference)))
924
+
925
+ (defun singular-error (&rest message-args)
926
+ "Apply `message' on MESSAGE-ARGS and do a `ding'.
927
+ This function should be used instead of `error' in hooks where calling
928
+ `error' is not a good idea."
929
+ (apply 'message message-args)
930
+ (ding))
931
+
932
+ (defun singular-pop-to-buffer (same-window &rest pop-to-buffer-args)
933
+ "Pop to buffer in same or other window.
934
+ Pops to buffer in same window if SAME-WINDOW equals t. Pops to buffer in
935
+ other window if SAME-WINDOW equals nil. If SAME-WINDOW equals neither t
936
+ nor nil the default behaviour of `pop-to-buffer' is used. The rest of the
937
+ arguments is passed unchanged to `pop-to-buffer'."
938
+ (let ((same-window-buffer-names
939
+ (cond
940
+ ((null same-window)
941
+ nil)
942
+ ((eq same-window t)
943
+ (let* ((buffer-or-name (car pop-to-buffer-args))
944
+ (buffer-name (if (bufferp buffer-or-name)
945
+ (buffer-name buffer-or-name)
946
+ buffer-or-name)))
947
+ (list buffer-name)))
948
+ (t
949
+ same-window-buffer-names))))
950
+ (apply 'pop-to-buffer pop-to-buffer-args)))
951
+ ;;}}}
952
+
953
+ ;;{{{ Miscellaneous interactive
954
+ (defun singular-recenter (&optional arg)
955
+ "Center point in window and redisplay frame. With ARG, put point on line ARG.
956
+ The desired position of point is always relative to the current window.
957
+ Just C-u as prefix means put point in the center of the window.
958
+ If ARG is omitted or nil, erases the entire frame and then redraws with
959
+ point in the center of the current window.
960
+ Scrolls window to the left margin and moves point to beginning of line."
961
+ (interactive "P")
962
+ (singular-reposition-point-and-window)
963
+ (recenter arg))
964
+
965
+ (defun singular-reposition-point-and-window ()
966
+ "Scroll window to the left margin and move point to beginning of line."
967
+ (interactive)
968
+ (set-window-hscroll (selected-window) 0)
969
+ (move-to-column 0)
970
+ ;; be careful where to place point
971
+ (singular-prompt-skip-forward))
972
+
973
+ (defun singular-toggle-truncate-lines ()
974
+ "Toggle `truncate-lines'.
975
+ A non-nil value of `truncate-lines' means do not display continuation
976
+ lines\; give each line of text one screen line.
977
+ Repositions window and point after toggling `truncate-lines'."
978
+ (interactive)
979
+ (setq truncate-lines (not truncate-lines))
980
+ ;; reposition so that user does not get confused
981
+ (singular-reposition-point-and-window)
982
+ ;; avoid calling `recenter' since it changes window layout more than
983
+ ;; necessary
984
+ (redraw-frame (selected-frame)))
985
+
986
+ ;; this is not a buffer-local variable even if at first glance it seems
987
+ ;; that it should be one. But if one changes buffer the contents of this
988
+ ;; variable becomes irrelevant since the last command is no longer a
989
+ ;; horizontal scroll command. The same is true for the initial value, so
990
+ ;; we set it to nil.
991
+ (defvar singular-scroll-previous-amount nil
992
+ "Amount of previous horizontal scroll command.")
993
+
994
+ (defun singular-scroll-right (&optional scroll-amount)
995
+ "Scroll selected window SCROLL-AMOUNT columns right.
996
+ SCROLL-AMOUNT defaults to amount of previous horizontal scroll command. If
997
+ the command immediately preceding this command has not been a horizontal
998
+ scroll command SCROLL-AMOUNT defaults to window width minus 2.
999
+ Moves point to leftmost visible column."
1000
+ (interactive "P")
1001
+
1002
+ ;; get amount to scroll
1003
+ (setq singular-scroll-previous-amount
1004
+ (cond (scroll-amount (prefix-numeric-value scroll-amount))
1005
+ ((eq last-command 'singular-scroll-horizontal)
1006
+ singular-scroll-previous-amount)
1007
+ (t (- (frame-width) 2)))
1008
+ this-command 'singular-scroll-horizontal)
1009
+
1010
+ ;; scroll
1011
+ (scroll-right singular-scroll-previous-amount)
1012
+ (move-to-column (window-hscroll))
1013
+ ;; be careful where to place point. But what if `(current-column)'
1014
+ ;; equals, say, one? Well, we simply do not care about that case.
1015
+ ;; Should not happen to often.
1016
+ (if (eq (current-column) 0)
1017
+ (singular-prompt-skip-forward)))
1018
+
1019
+ (defun singular-scroll-left (&optional scroll-amount)
1020
+ "Scroll selected window SCROLL-AMOUNT columns left.
1021
+ SCROLL-AMOUNT defaults to amount of previous horizontal scroll command. If
1022
+ the command immediately preceding this command has not been a horizontal
1023
+ scroll command SCROLL-AMOUNT defaults to window width minus 2.
1024
+ Moves point to leftmost visible column."
1025
+ (interactive "P")
1026
+
1027
+ ;; get amount to scroll
1028
+ (setq singular-scroll-previous-amount
1029
+ (cond (scroll-amount (prefix-numeric-value scroll-amount))
1030
+ ((eq last-command 'singular-scroll-horizontal)
1031
+ singular-scroll-previous-amount)
1032
+ (t (- (frame-width) 2)))
1033
+ this-command 'singular-scroll-horizontal)
1034
+
1035
+ ;; scroll
1036
+ (scroll-left singular-scroll-previous-amount)
1037
+ (move-to-column (window-hscroll))
1038
+ ;; be careful where to place point. But what if `(current-column)'
1039
+ ;; equals, say, one? Well, we simply do not care about that case.
1040
+ ;; Should not happen to often.
1041
+ (if (eq (current-column) 0)
1042
+ (singular-prompt-skip-forward)))
1043
+
1044
+ (defun singular-beginning-of-line (arg)
1045
+ "Move point to the beginning of line, then skip past prompt, if any.
1046
+ If prefix argument is given the prompt is not skipped."
1047
+ (interactive "P")
1048
+ (beginning-of-line)
1049
+ (if (not arg) (singular-prompt-skip-forward)))
1050
+
1051
+ (defun singular-load-file (file &optional noexpand)
1052
+ "Read a file into Singular (via '< \"FILE\";').
1053
+ If optional argument NOEXPAND is non-nil, FILE is left as it is entered by
1054
+ the user, otherwise it is expanded using `expand-file-name'."
1055
+ (interactive "fLoad file: ")
1056
+ (let* ((filename (if noexpand file (expand-file-name file)))
1057
+ (string (concat "< \"" filename "\";"))
1058
+ (process (singular-process)))
1059
+ (singular-input-filter process string)
1060
+ (singular-send-string process string)))
1061
+
1062
+ (defvar singular-load-library-history nil
1063
+ "History list for loading of Singular libraries.
1064
+ Is used by `singular-load-library'.")
1065
+
1066
+ (defun singular-load-library (nonstdlib &optional file)
1067
+ "Read a Singular library (via 'LIB \"FILE\";').
1068
+ If called interactively asks for the name of a standard Singular
1069
+ library. If called interactively with a prefix argument asks for a file
1070
+ name of a Singular library."
1071
+ (interactive "P")
1072
+ (let ((string (or file
1073
+ (if nonstdlib
1074
+ (read-file-name "Library file: ")
1075
+ (completing-read "Library: " singular-standard-libraries-alist
1076
+ nil nil nil 'singular-load-library-history))))
1077
+ (process (singular-process)))
1078
+ (setq string (concat "LIB \"" string "\";"))
1079
+ (singular-input-filter process string)
1080
+ (singular-send-string process string)))
1081
+ ;;}}}
1082
+
1083
+ ;;{{{ History
1084
+ (defcustom singular-history-ignoredups t
1085
+ "*If non-nil, do not add input matching the last on the input history."
1086
+ :type 'boolean
1087
+ :initialize 'custom-initialize-default
1088
+ :group 'singular-interactive-miscellaneous)
1089
+
1090
+ ;; this variable is used to set Comint's `comint-input-ring-size'
1091
+ (defcustom singular-history-size 64
1092
+ "*Size of the input history.
1093
+
1094
+ Changing this variable has no immediate effect even if one uses
1095
+ \\[customize] to do so. The new value will be used only in new Singular
1096
+ interactive mode buffers."
1097
+ :type 'integer
1098
+ :initialize 'custom-initialize-default
1099
+ :group 'singular-interactive-miscellaneous)
1100
+
1101
+ (defcustom singular-history-filter-regexp "\\`\\(..?\\|\\s *\\)\\'"
1102
+ "*Regular expression to filter strings *not* to insert in the input history.
1103
+ By default, input consisting of less than three characters and input
1104
+ consisting of white-space only is not inserted into the input history."
1105
+ :type 'regexp
1106
+ :initialize 'custom-initialize-default
1107
+ :group 'singular-interactive-miscellaneous)
1108
+
1109
+ (defcustom singular-history-explicit-file-name nil
1110
+ "*If non-nil, use this as file name to load and save the input history.
1111
+ If this variable equals nil, the `SINGULARHIST' environment variable is
1112
+ used to determine the file name.
1113
+ One should note that the input history is saved to file only on regular
1114
+ termination of Singular; that is, if one leaves Singular using the commands
1115
+ `quit\;' or `exit\;'."
1116
+ :type '(choice (const nil) file)
1117
+ :initialize 'custom-initialize-default
1118
+ :group 'singular-interactive-miscellaneous)
1119
+
1120
+ (defun singular-history-read ()
1121
+ "Read the input history from file.
1122
+ If `singular-history-explicit-file-name' is non-nil, uses that as file
1123
+ name, otherwise tries environment variable `SINGULARHIST'.
1124
+ This function is called from `singular-exec' every time a new Singular
1125
+ process is started."
1126
+ (singular-debug 'interactive (message "Reading input ring"))
1127
+ (let ((comint-input-ring-file-name (or singular-history-explicit-file-name
1128
+ (getenv "SINGULARHIST"))))
1129
+ ;; `comint-read-input-ring' does nothing if
1130
+ ;; `comint-input-ring-file-name' equals nil
1131
+ (comint-read-input-ring t)))
1132
+
1133
+ (defun singular-history-write ()
1134
+ "Write back the input history to file.
1135
+ If `singular-history-explicit-file-name' is non-nil, uses that as file
1136
+ name, otherwise tries environment variable `SINGULARHIST'.
1137
+ This function is called either by `singular-exit-singular' or by
1138
+ `singular-exit-sentinel' every time a Singular process terminates
1139
+ regularly."
1140
+ (singular-debug 'interactive (message "Writing input ring back"))
1141
+ (let ((comint-input-ring-file-name (or singular-history-explicit-file-name
1142
+ (getenv "SINGULARHIST"))))
1143
+ ;; `comint-write-input-ring' does nothing if
1144
+ ;; `comint-input-ring-file-name' equals nil
1145
+ (comint-write-input-ring)))
1146
+
1147
+ (defun singular-history-insert (input)
1148
+ "Insert string INPUT into the input history if necessary."
1149
+ (if (and (not (string-match singular-history-filter-regexp input))
1150
+ (or (not singular-history-ignoredups)
1151
+ (not (ring-p comint-input-ring))
1152
+ (ring-empty-p comint-input-ring)
1153
+ (not (string-equal (ring-ref comint-input-ring 0) input))))
1154
+ (ring-insert comint-input-ring input))
1155
+ (setq comint-input-ring-index nil))
1156
+
1157
+ (defun singular-history-init ()
1158
+ "Initialize variables concerning the input history.
1159
+
1160
+ This function is called at mode initialization time."
1161
+ (setq comint-input-ring-size singular-history-size))
1162
+ ;;}}}
1163
+
1164
+ ;;{{{ Simple section API for both Emacs and XEmacs
1165
+
1166
+ ;; Note:
1167
+ ;;
1168
+ ;; Sections and simple sections are used to mark Singular's input and
1169
+ ;; output for further access. Here are some general notes on simple
1170
+ ;; sections. Sections are explained in the respective folding.
1171
+ ;;
1172
+ ;; In general, simple sections are more or less Emacs' overlays or XEmacs
1173
+ ;; extents, resp. But they are more than simply an interface to overlays
1174
+ ;; or extents.
1175
+ ;;
1176
+ ;; - Simple sections are non-empty portions of text. They are interpreted
1177
+ ;; as left-closed, right-opened intervals, i.e., the start point of a
1178
+ ;; simple sections belongs to it whereas the end point does not.
1179
+ ;; - Simple sections start and end at line borders only.
1180
+ ;; - Simple sections do not overlap. Thus, any point in the buffer may be
1181
+ ;; covered by at most one simple section.
1182
+ ;; - Besides from their start and their end, simple sections have some type
1183
+ ;; associated.
1184
+ ;; - Simple sections are realized using overlays (extents for XEmacs)
1185
+ ;; which define the start and, end, and type (via properties) of the
1186
+ ;; simple section. Actually, as a lisp object a simple section is
1187
+ ;; nothing else but the underlying overlay.
1188
+ ;; - There may be so-called clear simple sections. Clear simple sections
1189
+ ;; do not have an underlying overlay. Instead, they start at the end of
1190
+ ;; the preceding non-clear simple section, end at the beginning of the
1191
+ ;; next non-clear simple section, and have the type defined by
1192
+ ;; `singular-simple-sec-clear-type'. Clear simple sections are
1193
+ ;; represented by nil.
1194
+ ;; - Buffer narrowing does not restrict the extent of completely or
1195
+ ;; partially inaccessible simple sections. But one should note that
1196
+ ;; some of the functions assume that there is no narrowing in
1197
+ ;; effect.
1198
+ ;; - After creation, simple sections are not modified any further.
1199
+ ;; - There is one nasty little corner case: what if a non-clear simple
1200
+ ;; section spans up to end of buffer? By definition, eob is not included
1201
+ ;; in that section since they are right-opened intervals. Most of the
1202
+ ;; functions react as if there is an imaginary empty clear simple section
1203
+ ;; at eob.
1204
+ ;; - Even though by now there are only two types of different simple
1205
+ ;; sections there may be an arbitrary number of them. Furthermore,
1206
+ ;; simple sections of different types may appear in arbitrary order.
1207
+ ;;
1208
+ ;; - In `singular-interactive-mode', the whole buffer is covered with
1209
+ ;; simple sections from the very beginning of the file up to the
1210
+ ;; beginning of the line containing the last input or output. The
1211
+ ;; remaining text up to `(point-max)' may be interpreted as covered by
1212
+ ;; one clear simple section. Thus, it is most reasonable to define
1213
+ ;; `input' to be the type of clear simple sections.
1214
+
1215
+ (defvar singular-simple-sec-clear-type 'input
1216
+ "Type of clear simple sections.
1217
+ If nil no clear simple sections are used.
1218
+
1219
+ One should not set this variable directly. Rather, one should customize
1220
+ `singular-section-face-alist'.")
1221
+
1222
+ (defvar singular-simple-sec-last-end nil
1223
+ "Marker at the end of the last simple section.
1224
+ Should be initialized by `singular-simple-sec-init' before any calls to
1225
+ `singular-simple-sec-create' are done. Instead of accessing this variable
1226
+ directly one should use the macro `singular-simple-sec-last-end-position'.
1227
+
1228
+ This variable is buffer-local.")
1229
+
1230
+ (defun singular-simple-sec-init (pos)
1231
+ "Initialize variables belonging to simple section management.
1232
+ Creates the buffer-local marker `singular-simple-sec-last-end' and
1233
+ initializes it to POS. POS should be at beginning of a line.
1234
+
1235
+ This function is called every time a new Singular session is started."
1236
+ (make-local-variable 'singular-simple-sec-last-end)
1237
+ (if (not (markerp singular-simple-sec-last-end))
1238
+ (setq singular-simple-sec-last-end (make-marker)))
1239
+ (set-marker singular-simple-sec-last-end pos))
1240
+
1241
+ (defmacro singular-simple-sec-last-end-position ()
1242
+ "Return the marker position of `singular-simple-sec-last-end'.
1243
+ This macro exists more or less for purposes of information hiding only."
1244
+ '(marker-position singular-simple-sec-last-end))
1245
+
1246
+ (defsubst singular-simple-sec-lookup-face (type)
1247
+ "Return the face to use for simple sections of type TYPE.
1248
+ This accesses the `singular-section-type-alist'. It does not harm if nil
1249
+ is associated with TYPE in that alist: In this case, this function will
1250
+ never be called for that TYPE."
1251
+ (cdr (assq type singular-section-face-alist)))
1252
+
1253
+ ;; Note:
1254
+ ;;
1255
+ ;; The rest of the folding is either marked as
1256
+ ;; Emacs
1257
+ ;; or
1258
+ ;; XEmacs
1259
+
1260
+ (singular-fset 'singular-simple-sec-create
1261
+ 'singular-emacs-simple-sec-create
1262
+ 'singular-xemacs-simple-sec-create)
1263
+
1264
+ (singular-fset 'singular-simple-sec-at
1265
+ 'singular-emacs-simple-sec-at
1266
+ 'singular-xemacs-simple-sec-at)
1267
+
1268
+ (singular-fset 'singular-simple-sec-start
1269
+ 'singular-emacs-simple-sec-start
1270
+ 'singular-xemacs-simple-sec-start)
1271
+
1272
+ (singular-fset 'singular-simple-sec-end
1273
+ 'singular-emacs-simple-sec-end
1274
+ 'singular-xemacs-simple-sec-end)
1275
+
1276
+ (singular-fset 'singular-simple-sec-type
1277
+ 'singular-emacs-simple-sec-type
1278
+ 'singular-xemacs-simple-sec-type)
1279
+
1280
+ (singular-fset 'singular-simple-sec-before
1281
+ 'singular-emacs-simple-sec-before
1282
+ 'singular-xemacs-simple-sec-before)
1283
+
1284
+ (singular-fset 'singular-simple-sec-start-at
1285
+ 'singular-emacs-simple-sec-start-at
1286
+ 'singular-xemacs-simple-sec-start-at)
1287
+
1288
+ (singular-fset 'singular-simple-sec-end-at
1289
+ 'singular-emacs-simple-sec-end-at
1290
+ 'singular-xemacs-simple-sec-end-at)
1291
+
1292
+ (singular-fset 'singular-simple-sec-in
1293
+ 'singular-emacs-simple-sec-in
1294
+ 'singular-xemacs-simple-sec-in)
1295
+ ;;}}}
1296
+
1297
+ ;;{{{ Simple section API for Emacs
1298
+ (defsubst singular-emacs-simple-sec-start (simple-sec)
1299
+ "Return start of non-clear simple section SIMPLE-SEC.
1300
+ Narrowing has no effect on this function."
1301
+ (overlay-start simple-sec))
1302
+
1303
+ (defsubst singular-emacs-simple-sec-end (simple-sec)
1304
+ "Return end of non-clear simple section SIMPLE-SEC.
1305
+ Narrowing has no effect on this function."
1306
+ (overlay-end simple-sec))
1307
+
1308
+ (defsubst singular-emacs-simple-sec-type (simple-sec)
1309
+ "Return type of SIMPLE-SEC.
1310
+ Returns nil if SIMPLE-SEC happens to be an overlay but not a simple
1311
+ section.
1312
+ Narrowing has no effect on this function."
1313
+ (if simple-sec
1314
+ (overlay-get simple-sec 'singular-type)
1315
+ singular-simple-sec-clear-type))
1316
+
1317
+ (defsubst singular-emacs-simple-sec-before (pos)
1318
+ "Return simple section before buffer position POS.
1319
+ This is the same as `singular-simple-sec-at' except if POS falls on a
1320
+ section border. In this case `singular-simple-section-before' returns the
1321
+ previous simple section instead of the current one. If POS falls on
1322
+ beginning of buffer, the simple section at beginning of buffer is returned.
1323
+ Narrowing has no effect on this function."
1324
+ (singular-emacs-simple-sec-at (max 1 (1- pos))))
1325
+
1326
+ (defun singular-emacs-simple-sec-create (type end)
1327
+ "Create a new simple section of type TYPE.
1328
+ Creates the section from end of previous simple section up to the first
1329
+ beginning of line before END. That position should be larger than or equal
1330
+ to `singular-simple-sec-last-end'. Updates `singular-simple-sec-last-end'.
1331
+ Returns the new simple section or `empty' if no simple section has been
1332
+ created.
1333
+ Assumes that no narrowing is in effect."
1334
+ (let ((last-end (singular-simple-sec-last-end-position))
1335
+ ;; `simple-sec' is the new simple section or `empty'
1336
+ simple-sec)
1337
+
1338
+ ;; get beginning of line before END. At this point we need that there
1339
+ ;; are no restrictions.
1340
+ (setq end (let ((old-point (point)))
1341
+ (goto-char end) (beginning-of-line)
1342
+ (prog1 (point) (goto-char old-point))))
1343
+
1344
+ (cond
1345
+ ;; do not create empty sections
1346
+ ((eq end last-end)
1347
+ 'empty)
1348
+ ;; non-clear simple sections
1349
+ ((not (eq type singular-simple-sec-clear-type))
1350
+ ;; if type has not changed we only have to extend the previous simple
1351
+ ;; section. If `last-end' happens to be 1 (meaning that we are
1352
+ ;; creating the first non-clear simple section in the buffer), then
1353
+ ;; `singular-simple-sec-before' returns nil,
1354
+ ;; `singular-simple-sec-type' returns the type of clear simple
1355
+ ;; sections that definitely does not equal TYPE, and a new simple
1356
+ ;; section is created as necessary.
1357
+ (setq simple-sec (singular-emacs-simple-sec-before last-end))
1358
+ (if (eq type (singular-emacs-simple-sec-type simple-sec))
1359
+ ;; move existing overlay
1360
+ (setq simple-sec (move-overlay simple-sec (overlay-start simple-sec) end))
1361
+ ;; create new overlay
1362
+ (setq simple-sec (make-overlay last-end end))
1363
+ ;; set type property
1364
+ (overlay-put simple-sec 'singular-type type)
1365
+ ;; set face
1366
+ (overlay-put simple-sec 'face (singular-simple-sec-lookup-face type))
1367
+ ;; evaporate empty sections
1368
+ (overlay-put simple-sec 'evaporate t))
1369
+ ;; update `singular-simple-sec-last-end' and return new simple
1370
+ ;; section
1371
+ (set-marker singular-simple-sec-last-end end)
1372
+ simple-sec)
1373
+ ;; clear simple sections
1374
+ (t
1375
+ ;; update `singular-simple-sec-last-end' and return nil
1376
+ (set-marker singular-simple-sec-last-end end)
1377
+ nil))))
1378
+
1379
+ (defun singular-emacs-simple-sec-start-at (pos)
1380
+ "Return start of clear simple section at position POS.
1381
+ Assumes the existence of an imaginary empty clear simple section if POS is
1382
+ at end of buffer and there is non-clear simple section immediately ending
1383
+ at POS.
1384
+ Assumes that no narrowing is in effect (since `previous-overlay-change'
1385
+ implicitly does so)."
1386
+ ;; yes, this `(1+ pos)' is OK at eob for
1387
+ ;; `singular-emacs-simple-sec-before' as well as
1388
+ ;; `previous-overlay-change'
1389
+ (let ((previous-overlay-change-pos (1+ pos)))
1390
+ ;; this `while' loop at last will run into the end of the next
1391
+ ;; non-clear simple section or stop at bob. Since POS may be right at
1392
+ ;; the end of a previous non-clear location, we have to search at least
1393
+ ;; one time from POS+1 backwards.
1394
+ (while (not (or (singular-emacs-simple-sec-before previous-overlay-change-pos)
1395
+ (eq previous-overlay-change-pos 1)))
1396
+ (setq previous-overlay-change-pos
1397
+ (previous-overlay-change previous-overlay-change-pos)))
1398
+ previous-overlay-change-pos))
1399
+
1400
+ (defun singular-emacs-simple-sec-end-at (pos)
1401
+ "Return end of clear simple section at position POS.
1402
+ Assumes the existence of an imaginary empty clear simple section if POS is
1403
+ at end of buffer and there is non-clear simple section immediately ending
1404
+ at POS.
1405
+ Assumes that no narrowing is in effect (since `next-overlay-change'
1406
+ implicitly does so)."
1407
+ (let ((next-overlay-change-pos (next-overlay-change pos)))
1408
+ ;; this `while' loop at last will run into the beginning of the next
1409
+ ;; non-clear simple section or stop at eob. Since POS may not be at
1410
+ ;; the beginning of a non-clear simple section we may start searching
1411
+ ;; immediately.
1412
+ (while (not (or (singular-emacs-simple-sec-at next-overlay-change-pos)
1413
+ (eq next-overlay-change-pos (point-max))))
1414
+ (setq next-overlay-change-pos
1415
+ (next-overlay-change next-overlay-change-pos)))
1416
+ next-overlay-change-pos))
1417
+
1418
+ (defun singular-emacs-simple-sec-at (pos)
1419
+ "Return simple section at buffer position POS.
1420
+ Assumes the existence of an imaginary empty clear simple section if POS is
1421
+ at end of buffer and there is non-clear simple section immediately ending
1422
+ at POS.
1423
+ Narrowing has no effect on this function."
1424
+ ;; at eob, `overlays-at' always returns nil so everything is OK for this
1425
+ ;; case, too
1426
+ (let ((overlays (overlays-at pos)) simple-sec)
1427
+ ;; be careful, there may be other overlays!
1428
+ (while (and overlays (not simple-sec))
1429
+ (if (singular-emacs-simple-sec-type (car overlays))
1430
+ (setq simple-sec (car overlays)))
1431
+ (setq overlays (cdr overlays)))
1432
+ simple-sec))
1433
+
1434
+ (defun singular-emacs-simple-sec-in (beg end)
1435
+ "Return a list of all simple sections intersecting with the region from BEG to END.
1436
+ A simple section intersects the region if the section and the region have
1437
+ at least one character in common. The sections are returned with
1438
+ startpoints in increasing order and clear simple sections (that is, nil's)
1439
+ inserted as necessary. BEG is assumed to be less than or equal to END.
1440
+ The imaginary empty clear simple section at end of buffer is never included
1441
+ in the result.
1442
+ Narrowing has no effect on this function."
1443
+ (let (overlays overlay-cursor)
1444
+ (if (= beg end)
1445
+ ;; `overlays-in' seems not be correct with respect to this case
1446
+ nil
1447
+ ;; go to END since chances are good that the overlays come in correct
1448
+ ;; order, then
1449
+ (setq overlays (let ((old-point (point)))
1450
+ (goto-char end)
1451
+ (prog1 (overlays-in beg end)
1452
+ (goto-char old-point)))
1453
+
1454
+ ;; now, turn overlays that are not simple sections into nils
1455
+ overlays (mapcar (function
1456
+ (lambda (overlay)
1457
+ (and (singular-emacs-simple-sec-type overlay)
1458
+ overlay)))
1459
+ overlays)
1460
+ ;; then, remove nils from list
1461
+ overlays (delq nil overlays)
1462
+ ;; now, we have to sort the list since documentation of `overlays-in'
1463
+ ;; does not state anything about the order the overlays are returned in
1464
+ overlays
1465
+ (sort overlays
1466
+ (function
1467
+ (lambda (a b)
1468
+ (< (overlay-start a) (overlay-start b))))))
1469
+
1470
+ ;; at last, we have the list of non-clear simple sections. Now, go and
1471
+ ;; insert clear simple sections as necessary.
1472
+ (if (null overlays)
1473
+ ;; if there are no non-clear simple sections at all there can be
1474
+ ;; only one large clear simple section
1475
+ '(nil)
1476
+ ;; we care about inside clear simple section first
1477
+ (setq overlay-cursor overlays)
1478
+ (while (cdr overlay-cursor)
1479
+ (if (eq (overlay-end (car overlay-cursor))
1480
+ (overlay-start (cadr overlay-cursor)))
1481
+ (setq overlay-cursor (cdr overlay-cursor))
1482
+ ;; insert nil
1483
+ (setcdr overlay-cursor
1484
+ (cons nil (cdr overlay-cursor)))
1485
+ (setq overlay-cursor (cddr overlay-cursor))))
1486
+ ;; now, check BEG and END for clear simple sections
1487
+ (if (> (overlay-start (car overlays)) beg)
1488
+ (setq overlays (cons nil overlays)))
1489
+ ;; `overlay-cursor' still points to the end
1490
+ (if (< (overlay-end (car overlay-cursor)) end)
1491
+ (setcdr overlay-cursor (cons nil nil)))
1492
+ overlays))))
1493
+ ;;}}}
1494
+
1495
+ ;;{{{ Simple section API for XEmacs
1496
+ (defsubst singular-xemacs-simple-sec-start (simple-sec)
1497
+ "Return start of non-clear simple section SIMPLE-SEC.
1498
+ Narrowing has no effect on this function."
1499
+ (extent-start-position simple-sec))
1500
+
1501
+ (defsubst singular-xemacs-simple-sec-end (simple-sec)
1502
+ "Return end of non-clear simple section SIMPLE-SEC.
1503
+ Narrowing has no effect on this function."
1504
+ (extent-end-position simple-sec))
1505
+
1506
+ (defsubst singular-xemacs-simple-sec-type (simple-sec)
1507
+ "Return type of SIMPLE-SEC.
1508
+ Returns nil if SIMPLE-SEC happens to be an extent but not a simple
1509
+ section.
1510
+ Narrowing has no effect on this function."
1511
+ (if simple-sec
1512
+ (extent-property simple-sec 'singular-type)
1513
+ singular-simple-sec-clear-type))
1514
+
1515
+ (defsubst singular-xemacs-simple-sec-before (pos)
1516
+ "Return simple section before buffer position POS.
1517
+ This is the same as `singular-simple-sec-at' except if POS falls on a
1518
+ section border. In this case `singular-simple-section-before' returns the
1519
+ previous simple section instead of the current one. If POS falls on
1520
+ beginning of buffer, the simple section at beginning of buffer is returned.
1521
+ Narrowing has no effect on this function."
1522
+ (singular-xemacs-simple-sec-at (max 1 (1- pos))))
1523
+
1524
+ (defun singular-xemacs-simple-sec-create (type end)
1525
+ "Create a new simple section of type TYPE.
1526
+ Creates the section from end of previous simple section up to the first
1527
+ beginning of line before END. That position should be larger than or equal
1528
+ to `singular-simple-sec-last-end'. Updates `singular-simple-sec-last-end'.
1529
+ Returns the new simple section or `empty' if no simple section has been
1530
+ created.
1531
+ Assumes that no narrowing is in effect."
1532
+ (let ((last-end (singular-simple-sec-last-end-position))
1533
+ ;; `simple-sec' is the new simple section or `empty'
1534
+ simple-sec)
1535
+
1536
+ ;; get beginning of line before END. At this point we need that there
1537
+ ;; are no restrictions.
1538
+ (setq end (let ((old-point (point)))
1539
+ (goto-char end) (beginning-of-line)
1540
+ (prog1 (point) (goto-char old-point))))
1541
+
1542
+ (cond
1543
+ ;; do not create empty sections
1544
+ ((eq end last-end)
1545
+ 'empty)
1546
+ ;; non-clear simple sections
1547
+ ((not (eq type singular-simple-sec-clear-type))
1548
+ ;; if type has not changed we only have to extend the previous simple
1549
+ ;; section. If `last-end' happens to be 1 (meaning that we are
1550
+ ;; creating the first non-clear simple section in the buffer), then
1551
+ ;; `singular-simple-sec-before' returns nil,
1552
+ ;; `singular-simple-sec-type' returns the type of clear simple
1553
+ ;; sections that definitely does not equal TYPE, and a new simple
1554
+ ;; section is created as necessary.
1555
+ (setq simple-sec (singular-xemacs-simple-sec-before last-end))
1556
+ (if (eq type (singular-xemacs-simple-sec-type simple-sec))
1557
+ ;; move existing extent
1558
+ (setq simple-sec (set-extent-endpoints simple-sec
1559
+ (extent-start-position simple-sec) end))
1560
+ ;; create new extent
1561
+ (setq simple-sec (make-extent last-end end))
1562
+ ;; set type property
1563
+ (set-extent-property simple-sec 'singular-type type)
1564
+ ;; set face. In contrast to Emacs, we do not need to set somethin
1565
+ ;; like `evaporate'. `detachable' is set by XEmacs by default.
1566
+ (set-extent-property simple-sec 'face (singular-simple-sec-lookup-face type)))
1567
+ ;; update `singular-simple-sec-last-end' and return new simple
1568
+ ;; section
1569
+ (set-marker singular-simple-sec-last-end end)
1570
+ simple-sec)
1571
+ ;; clear simple sections
1572
+ (t
1573
+ ;; update `singular-simple-sec-last-end' and return nil
1574
+ (set-marker singular-simple-sec-last-end end)
1575
+ nil))))
1576
+
1577
+ (defun singular-xemacs-simple-sec-start-at (pos)
1578
+ "Return start of clear simple section at position POS.
1579
+ Assumes the existence of an imaginary empty clear simple section if POS is
1580
+ at end of buffer and there is non-clear simple section immediately ending
1581
+ at POS.
1582
+ Assumes that no narrowing is in effect (since `previous-extent-change'
1583
+ implicitly does so)."
1584
+ ;; get into some hairy details at end of buffer. Look if there is a
1585
+ ;; non-clear simple section immediately ending at end of buffer and
1586
+ ;; return the start of the imaginary empty clear simple section in that
1587
+ ;; case. If buffer is empty this test fails since
1588
+ ;; `singular-xemacs-simple-sec-before' (correctly) returns nil. But in
1589
+ ;; that case the following loop returns the correct result.
1590
+ (if (and (eq pos (point-max))
1591
+ (singular-xemacs-simple-sec-before pos))
1592
+ pos
1593
+ (let ((previous-extent-change-pos (min (1+ pos) (point-max))))
1594
+ ;; this `while' loop at last will run into the end of the next
1595
+ ;; non-clear simple section or stop at bob. Since POS may be right at
1596
+ ;; the end of a previous non-clear location, we have to search at least
1597
+ ;; one time from POS+1 backwards.
1598
+ (while (not (or (singular-xemacs-simple-sec-before previous-extent-change-pos)
1599
+ (eq previous-extent-change-pos 1)))
1600
+ (setq previous-extent-change-pos
1601
+ (previous-extent-change previous-extent-change-pos)))
1602
+ previous-extent-change-pos)))
1603
+
1604
+ (defun singular-xemacs-simple-sec-end-at (pos)
1605
+ "Return end of clear simple section at position POS.
1606
+ Assumes the existence of an imaginary empty clear simple section if POS is
1607
+ at end of buffer and there is non-clear simple section immediately ending
1608
+ at POS.
1609
+ Assumes that no narrowing is in effect (since `next-extent-change'
1610
+ implicitly does so)."
1611
+ (let ((next-extent-change-pos (next-extent-change pos)))
1612
+ ;; this `while' loop at last will run into the beginning of the next
1613
+ ;; non-clear simple section or stop at eob. Since POS may not be at
1614
+ ;; the beginning of a non-clear simple section we may start searching
1615
+ ;; immediately.
1616
+ (while (not (or (singular-xemacs-simple-sec-at next-extent-change-pos)
1617
+ (eq next-extent-change-pos (point-max))))
1618
+ (setq next-extent-change-pos
1619
+ (next-extent-change next-extent-change-pos)))
1620
+ next-extent-change-pos))
1621
+
1622
+ (defun singular-xemacs-simple-sec-at (pos)
1623
+ "Return simple section at buffer position POS.
1624
+ Assumes the existence of an imaginary empty clear simple section if POS is
1625
+ at end of buffer and there is non-clear simple section immediately ending
1626
+ at POS.
1627
+ Narrowing has no effect on this function."
1628
+ ;; at eob, `map-extent' always returns nil so everything is OK for this
1629
+ ;; case, too. Do not try to use `extent-at' at this point. `extent-at'
1630
+ ;; does not return extents outside narrowed text.
1631
+ (map-extents (function (lambda (ext args) ext))
1632
+ nil pos pos nil nil 'singular-type))
1633
+
1634
+ (defun singular-xemacs-simple-sec-in (beg end)
1635
+ "Return a list of all simple sections intersecting with the region from BEG to END.
1636
+ A simple section intersects the region if the section and the region have
1637
+ at least one character in common. The sections are returned with
1638
+ startpoints in increasing order and clear simple sections (that is, nil's)
1639
+ inserted as necessary. BEG is assumed to be less than or equal to END.
1640
+ The imaginary empty clear simple section at end of buffer is never included
1641
+ in the result.
1642
+ Narrowing has no effect on this function."
1643
+ (let (extents extent-cursor)
1644
+ (if (= beg end)
1645
+ ;; `mapcar-extents' may return some extents in this case, so
1646
+ ;; exclude it
1647
+ nil
1648
+ ;; OK, that's a little bit easier than for Emacs ...
1649
+ (setq extents (mapcar-extents 'identity nil nil beg end nil 'singular-type))
1650
+
1651
+ ;; now we have the list of non-clear simple sections. Go and
1652
+ ;; insert clear simple sections as necessary.
1653
+ (if (null extents)
1654
+ ;; if there are no non-clear simple sections at all there can be
1655
+ ;; only one large clear simple section
1656
+ '(nil)
1657
+ ;; we care about inside clear simple section first
1658
+ (setq extent-cursor extents)
1659
+ (while (cdr extent-cursor)
1660
+ (if (eq (extent-end-position (car extent-cursor))
1661
+ (extent-start-position (cadr extent-cursor)))
1662
+ (setq extent-cursor (cdr extent-cursor))
1663
+ ;; insert nil
1664
+ (setcdr extent-cursor
1665
+ (cons nil (cdr extent-cursor)))
1666
+ (setq extent-cursor (cddr extent-cursor))))
1667
+ ;; now, check BEG and END for clear simple sections
1668
+ (if (> (extent-start-position (car extents)) beg)
1669
+ (setq extents (cons nil extents)))
1670
+ ;; `extent-cursor' still points to the end
1671
+ (if (< (extent-end-position (car extent-cursor)) end)
1672
+ (setcdr extent-cursor (cons nil nil)))
1673
+ extents))))
1674
+ ;;}}}
1675
+
1676
+ ;;{{{ Section API
1677
+
1678
+ ;; Note:
1679
+ ;;
1680
+ ;; Sections are built on simple sections. Their purpose is to cover the
1681
+ ;; difference between clear and non-clear simple sections.
1682
+ ;;
1683
+ ;; - Sections consist of a simple section, its type, and its start and end
1684
+ ;; points. This is redundant information only in the case of non-clear
1685
+ ;; simple section.
1686
+ ;; - Sections are read-only objects, neither are they modified nor are they
1687
+ ;; created.
1688
+ ;; - Buffer narrowing does not restrict the extent of completely or
1689
+ ;; partially inaccessible sections. In contrast to simple sections the
1690
+ ;; functions concerning sections do not assume that there is no narrowing
1691
+ ;; in effect. However, most functions provide an optional argument
1692
+ ;; RESTRICTED that restricts the start and end point of the returned
1693
+ ;; sections to the currently active restrictions. Of course, that does
1694
+ ;; not affect the range of the underlying simple sections, only the
1695
+ ;; additional start and end points being returned. One should note that
1696
+ ;; by restricting sections one may get empty sections, that is, sections
1697
+ ;; for which the additional start and end point are equal.
1698
+ ;; - In many cases it is not desirable that the user operates on sections
1699
+ ;; which are not completely accessible. To check that a section is
1700
+ ;; completely accessible the `singular-section-check' function should be
1701
+ ;; used.
1702
+ ;; - Sections are independent from implementation dependencies. There are
1703
+ ;; no different versions of the functions for Emacs and XEmacs.
1704
+ ;; - Whenever possible, one should not access simple section directly.
1705
+ ;; Instead, one should use the section API.
1706
+
1707
+ (defcustom singular-section-face-alist '((input . nil)
1708
+ (output . singular-section-output-face))
1709
+ "*Alist that maps section types to faces.
1710
+ Should be a list consisting of elements (SECTION-TYPE . FACE-OR-NIL), where
1711
+ SECTION-TYPE is either `input' or `output'.
1712
+
1713
+ At any time, the Singular interactive mode buffer is completely covered by
1714
+ sections of two different types: input sections and output sections. This
1715
+ variable determines which faces are used to display the different sections.
1716
+
1717
+ If for type SECTION-TYPE the value FACE-OR-NIL is a face it is used to
1718
+ display the contents of all sections of that particular type.
1719
+ If instead FACE-OR-NIL equals nil sections of that type become so-called
1720
+ clear sections. The content of clear sections is displayed as regular
1721
+ text, with no faces at all attached to them.
1722
+
1723
+ Some notes and restrictions on this variable (believe them or not):
1724
+ o Changing this variable during a Singular session may cause unexpected
1725
+ results (but not too serious ones, though).
1726
+ o There may be only one clear section type defined at a time.
1727
+ o Choosing clear input sections is a good idea.
1728
+ o Choosing clear output sections is a bad idea.
1729
+ o Consequence: Not to change this variable is a good idea."
1730
+ ;; to add new section types, simply extend the `list' widget.
1731
+ ;; The rest should work unchanged. Do not forget to update docu.
1732
+ :type '(list (cons :tag "Input sections"
1733
+ (const :format "" input)
1734
+ (choice :format
1735
+ "Choose either clear or non-clear input sections. For non-clear sections,
1736
+ select or modify a face (preferably `singular-section-input-face') used to
1737
+ display the sections.
1738
+ %[Choice%]
1739
+ %v
1740
+ "
1741
+ (const :tag "Clear sections" nil)
1742
+ (face :tag "Non-clear sections")))
1743
+ (cons :tag "Output sections"
1744
+ (const :format "" output)
1745
+ (choice :format
1746
+ "Choose either clear or non-clear output sections. For non-clear sections,
1747
+ select or modify a face (preferably `singular-section-output-face') used to
1748
+ display the sections.
1749
+ %[Choice%]
1750
+ %v
1751
+ "
1752
+ (const :tag "Clear sections" nil)
1753
+ (face :tag "Non-clear sections"))))
1754
+ :initialize 'custom-initialize-reset
1755
+ ;; this function checks for validity (only one clear section
1756
+ ;; type) and sets `singular-simple-sec-clear-type' accordingly.
1757
+ ;; In case of an error, nothing is set or modified.
1758
+ :set (function (lambda (var value)
1759
+ (let* ((cdrs-with-nils (mapcar 'cdr value))
1760
+ (cdrs-without-nils (delq nil (copy-sequence cdrs-with-nils))))
1761
+ (if (> (- (length cdrs-with-nils) (length cdrs-without-nils)) 1)
1762
+ (error "Only one clear section type allowed (see `singular-section-face-alist')")
1763
+ (set-default var value)
1764
+ (setq singular-simple-sec-clear-type (car (rassq nil value)))))))
1765
+ :group 'singular-faces
1766
+ :group 'singular-sections-and-foldings)
1767
+
1768
+ (defface singular-section-input-face '((t nil))
1769
+ "*Face to use for input sections.
1770
+ It may be not sufficient to modify this face to change the appearance of
1771
+ input sections. See `singular-section-face-alist' for more information."
1772
+ :group 'singular-faces
1773
+ :group 'singular-sections-and-foldings)
1774
+
1775
+ (defface singular-section-output-face '((t (:bold t)))
1776
+ "*Face to use for output sections.
1777
+ It may be not sufficient to modify this face to change the appearance of
1778
+ output sections. See `singular-section-face-alist' for more information."
1779
+ :group 'singular-faces
1780
+ :group 'singular-sections-and-foldings)
1781
+
1782
+ (defsubst singular-section-create (simple-sec type start end)
1783
+ "Create and return a new section."
1784
+ (vector simple-sec type start end))
1785
+
1786
+ (defsubst singular-section-simple-sec (section)
1787
+ "Return underlying simple section of SECTION."
1788
+ (aref section 0))
1789
+
1790
+ (defsubst singular-section-type (section)
1791
+ "Return type of SECTION."
1792
+ (aref section 1))
1793
+
1794
+ (defsubst singular-section-start (section)
1795
+ "Return start of SECTION."
1796
+ (aref section 2))
1797
+
1798
+ (defsubst singular-section-end (section)
1799
+ "Return end of SECTION."
1800
+ (aref section 3))
1801
+
1802
+ (defun singular-section-at (pos &optional restricted)
1803
+ "Return section at position POS.
1804
+ Returns section intersected with current restriction if RESTRICTED is
1805
+ non-nil."
1806
+ (let* ((simple-sec (singular-simple-sec-at pos))
1807
+ (type (singular-simple-sec-type simple-sec))
1808
+ start end)
1809
+ (if simple-sec
1810
+ (setq start (singular-simple-sec-start simple-sec)
1811
+ end (singular-simple-sec-end simple-sec))
1812
+ (save-restriction
1813
+ (widen)
1814
+ (setq start (singular-simple-sec-start-at pos)
1815
+ end (singular-simple-sec-end-at pos))))
1816
+ (cond
1817
+ ;; not restricted first
1818
+ ((not restricted)
1819
+ (singular-section-create simple-sec type start end))
1820
+ ;; restricted and degenerated
1821
+ ((and restricted
1822
+ (< end (point-min)))
1823
+ (singular-section-create simple-sec type (point-min) (point-min)))
1824
+ ;; restricted and degenerated
1825
+ ((and restricted
1826
+ (> start (point-max)))
1827
+ (singular-section-create simple-sec type (point-max) (point-max)))
1828
+ ;; restricted but not degenerated
1829
+ (t
1830
+ (singular-section-create simple-sec type
1831
+ (max start (point-min))
1832
+ (min end (point-max)))))))
1833
+
1834
+ (defun singular-section-before (pos &optional restricted)
1835
+ "Return section before position POS.
1836
+ This is the same as `singular-section-at' except if POS falls on a section
1837
+ border. In this case `singular-section-before' returns the previous
1838
+ section instead of the current one. If POS falls on beginning of buffer,
1839
+ the section at beginning of buffer is returned.
1840
+ Returns section intersected with current restriction if RESTRICTED is
1841
+ non-nil."
1842
+ (singular-section-at (max 1 (1- pos)) restricted))
1843
+
1844
+ (defun singular-section-in (beg end &optional restricted)
1845
+ "Return a list of all sections intersecting with the region from BEG to END.
1846
+ A section intersects with the region if the section and the region have at
1847
+ least one character in common. The sections are returned in increasing
1848
+ order.
1849
+ If optional argument RESTRICTED is non-nil only sections which are
1850
+ completely in the intersection of the region and the current restriction
1851
+ are returned."
1852
+ ;; exchange BEG and END if necessary as a special service to our users
1853
+ (let* ((reg-beg (min beg end))
1854
+ (reg-end (max beg end))
1855
+ ;; we need these since we widen the buffer later on
1856
+ (point-min (point-min))
1857
+ (point-max (point-max))
1858
+ simple-sections)
1859
+ (if (and restricted
1860
+ (or (> reg-beg point-max) (< reg-end point-min)))
1861
+ ;; degenerate restrictions
1862
+ nil
1863
+ ;; do the intersection if necessary and get simple sections
1864
+ (setq reg-beg (if restricted (max reg-beg point-min) reg-beg)
1865
+ reg-end (if restricted (min reg-end point-max) reg-end)
1866
+ simple-sections (singular-simple-sec-in reg-beg reg-end))
1867
+ ;; we still have REG-BEG <= REG-END in any case. SIMPLE-SECTIONS
1868
+ ;; contains the list of simple sections intersecting with the region
1869
+ ;; from REG-BEG and REG-END.
1870
+
1871
+ (if (null simple-sections)
1872
+ nil
1873
+ ;; and here we even have REG-BEG < REG-END
1874
+ (save-restriction
1875
+ (widen)
1876
+ ;; get sections intersecting with the region from REG-BEG to
1877
+ ;; REG-END
1878
+ (let* ((sections (singular-section-in-internal simple-sections
1879
+ reg-beg reg-end))
1880
+ first-section-start last-section-end)
1881
+ (if (not restricted)
1882
+ sections
1883
+ (setq first-section-start (singular-section-start (car sections))
1884
+ last-section-end (singular-section-end (car (last sections))))
1885
+ ;; popping off first element is easy ...
1886
+ (if (< first-section-start point-min)
1887
+ (setq sections (cdr sections)))
1888
+ ;; ... but last element is harder to pop off
1889
+ (cond
1890
+ (;; no elements left
1891
+ (null sections)
1892
+ nil)
1893
+ (;; one element left
1894
+ (null (cdr sections))
1895
+ (if (> last-section-end point-max)
1896
+ nil
1897
+ sections))
1898
+ (;; more than one element left
1899
+ t
1900
+ (if (> last-section-end point-max)
1901
+ (setcdr (last sections 2) nil))
1902
+ sections)))))))))
1903
+
1904
+ (defun singular-section-in-internal (simple-sections reg-beg reg-end)
1905
+ "Create a list of sections from SIMPLE-SECTIONS.
1906
+ This is the back-end for `singular-section-in'.
1907
+ First simple section should be such that it contains REG-BEG, last simple
1908
+ section should be such that it contains or ends at REG-END. These
1909
+ arguments are used to find the start resp. end of clear simple sections of
1910
+ terminal clear simple sections in SIMPLE-SECTIONS.
1911
+ Assumes that REG-BEG < REG-END.
1912
+ Assumes that SIMPLE-SECTIONS is not empty.
1913
+ Assumes that no narrowing is in effect."
1914
+ (let* (;; we pop off the extra nil at the end of the loop
1915
+ (sections (cons nil nil))
1916
+ (sections-end sections)
1917
+ (simple-section (car simple-sections))
1918
+ type start end)
1919
+
1920
+ ;; first, get unrestricted start
1921
+ (setq start (if simple-section
1922
+ (singular-simple-sec-start simple-section)
1923
+ ;; here we need that no narrowing is in effect
1924
+ (singular-simple-sec-start-at reg-beg)))
1925
+
1926
+ ;; loop through all simple sections but last
1927
+ (while (cdr simple-sections)
1928
+ (setq simple-section (car simple-sections)
1929
+ type (singular-simple-sec-type simple-section)
1930
+ end (if simple-section
1931
+ (singular-simple-sec-end simple-section)
1932
+ (singular-simple-sec-start (cadr simple-sections)))
1933
+
1934
+ ;; append the new section to `sections-end'
1935
+ sections-end
1936
+ (setcdr sections-end
1937
+ (cons (singular-section-create simple-section type start end) nil))
1938
+
1939
+ ;; get next simple section and its start
1940
+ simple-sections (cdr simple-sections)
1941
+ start end))
1942
+
1943
+ ;; care about last simple section
1944
+ (setq simple-section (car simple-sections)
1945
+ type (singular-simple-sec-type simple-section)
1946
+ end (if simple-section
1947
+ (singular-simple-sec-end simple-section)
1948
+ ;; the `1-' is OK since REG-BEG < REG-END.
1949
+ ;; here we need that no narrowing is in effect
1950
+ (singular-simple-sec-end-at (1- reg-end))))
1951
+ (setcdr sections-end
1952
+ (cons (singular-section-create simple-section type start end) nil))
1953
+
1954
+ ;; we should not forget to pop off our auxiliary cons-cell
1955
+ (cdr sections)))
1956
+
1957
+ (defun singular-section-mapsection (func sections &optional type-filter negate-filter)
1958
+ "Apply FUNC to each section in SECTIONS, and make a list of the results.
1959
+ If optional argument TYPE-FILTER is non-nil it should be a list of section
1960
+ types. FUNC is then applied only to those sections with type occurring in
1961
+ TYPE-FILTER. If in addition optional argument NEGATE-FILTER is non-nil
1962
+ FUNC is applied only to those sections with type not occurring in
1963
+ TYPE-FILTER.
1964
+
1965
+ In any case the length of the list this function returns equals the
1966
+ number of sections actually processed."
1967
+ (if (not type-filter)
1968
+ (mapcar func sections)
1969
+ ;; copy the list first
1970
+ (let ((sections (copy-sequence sections)))
1971
+ ;; filter elements and turn them to t's
1972
+ (setq sections
1973
+ (mapcar (function
1974
+ (lambda (section)
1975
+ ;; that strange expression evaluates to t iff the
1976
+ ;; section should be removed. The `not' is to
1977
+ ;; canonize boolean values to t or nil, resp.
1978
+ (or (eq (not (memq (singular-section-type section) type-filter))
1979
+ (not negate-filter))
1980
+ section)))
1981
+ sections)
1982
+
1983
+ ;; remove t's now
1984
+ sections (delq t sections))
1985
+
1986
+ ;; call function for remaining sections
1987
+ (mapcar func sections))))
1988
+ ;;}}}
1989
+
1990
+ ;;{{{ Section miscellaneous
1991
+ (defun singular-section-check (section &optional no-error)
1992
+ "Check whether SECTION is completely accessible and return t if so.
1993
+ If otherwise SECTION is restricted either in part or as a whole, this
1994
+ function fails with an error or returns nil if optional argument NO-ERROR
1995
+ is non-nil."
1996
+ (cond ((and (>= (singular-section-start section) (point-min))
1997
+ (<= (singular-section-end section) (point-max))) t)
1998
+ (no-error nil)
1999
+ (t (error "section is restricted either in part or as a whole"))))
2000
+
2001
+ (defun singular-section-to-string (section &optional raw)
2002
+ "Get contents of SECTION as a string.
2003
+ Returns text between start and end of SECTION.
2004
+ Removes prompts from section contents unless optional argument RAW is
2005
+ non-nil.
2006
+ Narrowing has no effect on this function."
2007
+ (save-restriction
2008
+ (widen)
2009
+ (let ((string (buffer-substring (singular-section-start section)
2010
+ (singular-section-end section))))
2011
+ (if raw
2012
+ string
2013
+ (singular-prompt-remove-string string)))))
2014
+ ;;}}}
2015
+
2016
+ ;;{{{ Section miscellaneous interactive
2017
+ (defun singular-section-goto-beginning ()
2018
+ "Move point to beginning of current section."
2019
+ (interactive)
2020
+ (goto-char (singular-section-start (singular-section-at (point))))
2021
+ (singular-keep-region-active))
2022
+
2023
+ (defun singular-section-goto-end ()
2024
+ "Move point to end of current section."
2025
+ (interactive)
2026
+ (goto-char (singular-section-end (singular-section-at (point))))
2027
+ (singular-keep-region-active))
2028
+
2029
+ (defun singular-section-backward (n)
2030
+ "Move backward until encountering the beginning of a section.
2031
+ With argument, do this that many times. With N less than zero, call
2032
+ `singular-section-forward' with argument -N."
2033
+ (interactive "p")
2034
+ (while (> n 0)
2035
+ (goto-char (singular-section-start (singular-section-before (point))))
2036
+ (setq n (1- n)))
2037
+ (if (< n 0)
2038
+ (singular-section-forward (- n))
2039
+ (singular-keep-region-active)))
2040
+
2041
+ (defun singular-section-forward (n)
2042
+ "Move forward until encountering the end of a section.
2043
+ With argument, do this that many times. With N less than zero, call
2044
+ `singular-section-backward' with argument -N."
2045
+ (interactive "p")
2046
+ (while (> n 0)
2047
+ (goto-char (singular-section-end (singular-section-at (point))))
2048
+ (setq n (1- n)))
2049
+ (if (< n 0)
2050
+ (singular-section-backward (- n))
2051
+ (singular-keep-region-active)))
2052
+
2053
+ (defun singular-section-kill (section &optional raw no-error)
2054
+ "Kill SECTION.
2055
+ Puts the contents of SECTION into the kill ring. Removes prompts from
2056
+ contents unless optional argument RAW is non-nil.
2057
+ If called interactively, kills section point currently is in. Does a raw
2058
+ section kill if called with a prefix argument, otherwise strips prompts.
2059
+ Does not kill sections that are restricted either in part or as a whole.
2060
+ Rather fails with an error in such cases or silently fails if optional
2061
+ argument NO-ERROR is non-nil."
2062
+ (interactive (list (singular-section-at (point))
2063
+ current-prefix-arg nil))
2064
+ (when (singular-section-check section no-error)
2065
+ (kill-new (singular-section-to-string section raw))
2066
+ (delete-region (singular-section-start section)
2067
+ (singular-section-end section))))
2068
+ ;;}}}
2069
+
2070
+ ;;{{{ Folding sections for both Emacs and XEmacs
2071
+ (defcustom singular-folding-ellipsis "Singular I/O ..."
2072
+ "*Ellipsis to show for folded input or output.
2073
+ Changing this variable has an immediate effect only if one uses
2074
+ \\[customize] to do so.
2075
+ However, even then it may be necessary to refresh display completely (using
2076
+ \\[recenter], for example) for the new settings to be visible."
2077
+ :type 'string
2078
+ :initialize 'custom-initialize-default
2079
+ :set (function
2080
+ (lambda (var value)
2081
+ ;; set in all singular buffers
2082
+ (singular-map-buffer 'singular-folding-set-ellipsis value)
2083
+ (set-default var value)))
2084
+ :group 'singular-sections-and-foldings)
2085
+
2086
+ (defcustom singular-folding-line-move-ignore-folding t
2087
+ "*If non-nil, ignore folded sections when moving point up or down.
2088
+ This variable is used to initialize `line-move-ignore-invisible'. However,
2089
+ documentation states that setting `line-move-ignore-invisible' to a non-nil
2090
+ value may result in a slow-down when moving the point up or down. One
2091
+ should try to set this variable to nil if point motion seems too slow.
2092
+
2093
+ Changing this variable has an immediate effect only if one uses
2094
+ \\[customize] to do so."
2095
+ :type 'boolean
2096
+ :initialize 'custom-initialize-default
2097
+ :set (function
2098
+ (lambda (var value)
2099
+ ;; set in all singular buffers
2100
+ (singular-map-buffer 'set 'line-move-ignore-invisible value)
2101
+ (set-default var value)))
2102
+ :group 'singular-sections-and-foldings)
2103
+
2104
+ (defun singular-folding-set-ellipsis (ellipsis)
2105
+ "Set ellipsis to show for folded input or output in current buffer."
2106
+ (cond
2107
+ ;; Emacs
2108
+ ((eq singular-emacs-flavor 'emacs)
2109
+ (setq buffer-display-table (or (copy-sequence standard-display-table)
2110
+ (make-display-table)))
2111
+ (set-display-table-slot buffer-display-table
2112
+ 'selective-display (vconcat ellipsis)))
2113
+ ;; XEmacs
2114
+ (t
2115
+ (set-glyph-image invisible-text-glyph ellipsis (current-buffer)))))
2116
+
2117
+ (defun singular-folding-init ()
2118
+ "Initializes folding of sections for the current buffer.
2119
+ That includes setting `buffer-invisibility-spec' and the ellipsis to show
2120
+ for hidden text.
2121
+
2122
+ This function is called at mode initialization time."
2123
+ ;; initialize `buffer-invisibility-spec' first
2124
+ (let ((singular-invisibility-spec (cons 'singular-interactive-mode t)))
2125
+ (if (and (listp buffer-invisibility-spec)
2126
+ (not (member singular-invisibility-spec buffer-invisibility-spec)))
2127
+ (setq buffer-invisibility-spec
2128
+ (cons singular-invisibility-spec buffer-invisibility-spec))
2129
+ (setq buffer-invisibility-spec (list singular-invisibility-spec))))
2130
+ ;; ignore invisible lines on movements
2131
+ (set (make-local-variable 'line-move-ignore-invisible)
2132
+ singular-folding-line-move-ignore-folding)
2133
+ ;; now for the ellipsis
2134
+ (singular-folding-set-ellipsis singular-folding-ellipsis))
2135
+
2136
+ (defun singular-folding-fold (section &optional no-error)
2137
+ "Fold section SECTION if it is not already folded.
2138
+ Does not fold sections that do not end in a newline or that are restricted
2139
+ either in part or as a whole. Rather fails with an error in such cases
2140
+ or silently fails if optional argument NO-ERROR is non-nil.
2141
+ This is for safety only: In both cases the result may be confusing to the
2142
+ user."
2143
+ (let* ((start (singular-section-start section))
2144
+ (end (singular-section-end section)))
2145
+ (cond ((not (singular-section-check section no-error))
2146
+ nil)
2147
+ ((not (eq (char-before end) ?\n))
2148
+ (unless no-error
2149
+ (error "Section does not end in a newline")))
2150
+ ((not (singular-folding-foldedp section))
2151
+ ;; fold but only if not already folded
2152
+ (singular-folding-fold-internal section)))))
2153
+
2154
+ (defun singular-folding-unfold (section &optional no-error invisibility-overlay-or-extent)
2155
+ "Unfold section SECTION if it is not already unfolded.
2156
+ Does not unfold sections that are restricted either in part or as a whole.
2157
+ Rather fails with an error in such cases or silently fails if optional
2158
+ argument NO-ERROR is non-nil.
2159
+ This is for safety only: The result may be confusing to the user.
2160
+ If optional argument INVISIBILITY-OVERLAY-OR-EXTENT is non-nil it should be
2161
+ the invisibility overlay or extent, respectively, of the section to
2162
+ unfold."
2163
+ (let* ((start (singular-section-start section))
2164
+ (end (singular-section-end section)))
2165
+ (cond ((not (singular-section-check section no-error))
2166
+ nil)
2167
+ ((or invisibility-overlay-or-extent
2168
+ (setq invisibility-overlay-or-extent (singular-folding-foldedp section)))
2169
+ ;; unfold but only if not already unfolded
2170
+ (singular-folding-unfold-internal section invisibility-overlay-or-extent)))))
2171
+
2172
+ (defun singular-folding-fold-at-point ()
2173
+ "Fold section point currently is in.
2174
+ Does not fold sections that do not end in a newline or that are restricted
2175
+ either in part or as a whole. Rather fails with an error in such cases."
2176
+ (interactive)
2177
+ (singular-folding-fold (singular-section-at (point))))
2178
+
2179
+ (defun singular-folding-unfold-at-point ()
2180
+ "Unfold section point currently is in.
2181
+ Does not unfold sections that are restricted either in part or as a whole.
2182
+ Rather fails with an error in such cases."
2183
+ (interactive)
2184
+ (singular-folding-unfold (singular-section-at (point))))
2185
+
2186
+ (defun singular-folding-fold-latest-output ()
2187
+ "Fold latest output section.
2188
+ Does not fold sections that do not end in a newline or that are restricted
2189
+ either in part or as a whole. Rather fails with an error in such cases."
2190
+ (interactive)
2191
+ (singular-folding-fold (singular-latest-output-section)))
2192
+
2193
+ (defun singular-folding-unfold-latest-output ()
2194
+ "Unfolds latest output section.
2195
+ Does not unfold sections that are restricted either in part or as a whole.
2196
+ Rather fails with an error in such cases."
2197
+ (interactive)
2198
+ (singular-folding-unfold (singular-latest-output-section)))
2199
+
2200
+ (defun singular-folding-fold-all-output ()
2201
+ "Fold all complete, unfolded output sections.
2202
+ That is, all output sections that are not restricted in part or as a whole
2203
+ and that end in a newline."
2204
+ (interactive)
2205
+ (singular-section-mapsection (function (lambda (section) (singular-folding-fold section t)))
2206
+ (singular-section-in (point-min) (point-max) t)
2207
+ '(output)))
2208
+
2209
+ (defun singular-folding-unfold-all-output ()
2210
+ "Unfold all complete, folded output sections.
2211
+ That is, all output sections that are not restricted in part or as a whole."
2212
+ (interactive)
2213
+ (singular-section-mapsection (function (lambda (section) (singular-folding-unfold section t)))
2214
+ (singular-section-in (point-min) (point-max) t)
2215
+ '(output)))
2216
+
2217
+ (defun singular-folding-toggle-fold-at-point-or-all (&optional arg)
2218
+ "Fold or unfold section point currently is in or all output sections.
2219
+ Without prefix argument, folds unfolded sections and unfolds folded
2220
+ sections. With prefix argument, folds all output sections if argument is
2221
+ positive, otherwise unfolds all output sections.
2222
+ Does neither fold nor unfold sections that do not end in a newline or that
2223
+ are restricted either in part or as a whole. Rather fails with an error in
2224
+ such cases."
2225
+ (interactive "P")
2226
+ (cond ((not arg)
2227
+ ;; fold or unfold section at point
2228
+ (let* ((section (singular-section-at (point)))
2229
+ (invisibility-overlay-or-extent (singular-folding-foldedp section)))
2230
+ (if invisibility-overlay-or-extent
2231
+ (singular-folding-unfold section nil invisibility-overlay-or-extent)
2232
+ (singular-folding-fold section))))
2233
+ ((> (prefix-numeric-value arg) 0)
2234
+ (singular-folding-fold-all-output))
2235
+ (t
2236
+ (singular-folding-unfold-all-output))))
2237
+
2238
+ (defun singular-folding-toggle-fold-latest-output (&optional arg)
2239
+ "Fold or unfold latest output section.
2240
+ Folds unfolded sections and unfolds folded sections.
2241
+ Does neither fold nor unfold sections that do not end in a newline or that
2242
+ are restricted either in part or as a whole. Rather fails with an error in
2243
+ such cases."
2244
+ (interactive)
2245
+ (let* ((section (singular-latest-output-section))
2246
+ (invisibility-overlay-or-extent (singular-folding-foldedp section)))
2247
+ (if invisibility-overlay-or-extent
2248
+ (singular-folding-unfold section nil invisibility-overlay-or-extent)
2249
+ (singular-folding-fold section))))
2250
+
2251
+ ;; Note:
2252
+ ;;
2253
+ ;; The rest of the folding is either marked as
2254
+ ;; Emacs
2255
+ ;; or
2256
+ ;; XEmacs
2257
+
2258
+ (singular-fset 'singular-folding-fold-internal
2259
+ 'singular-emacs-folding-fold-internal
2260
+ 'singular-xemacs-folding-fold-internal)
2261
+
2262
+ (singular-fset 'singular-folding-unfold-internal
2263
+ 'singular-emacs-folding-unfold-internal
2264
+ 'singular-xemacs-folding-unfold-internal)
2265
+
2266
+ (singular-fset 'singular-folding-foldedp
2267
+ 'singular-emacs-folding-foldedp-internal
2268
+ 'singular-xemacs-folding-foldedp-internal)
2269
+ ;;}}}
2270
+
2271
+ ;;{{{ Folding sections for Emacs
2272
+
2273
+ ;; Note:
2274
+ ;;
2275
+ ;; For Emacs, we use overlays to hide text (so-called "invisibility
2276
+ ;; overlays"). In addition to their `invisible' property, they have the
2277
+ ;; `singular-invisible' property set. Setting the intangible property does
2278
+ ;; not work very well for Emacs. We use the variable
2279
+ ;; `line-move-ignore-invisible' which works quite well.
2280
+
2281
+ (defun singular-emacs-folding-fold-internal (section)
2282
+ "Fold section SECTION.
2283
+ SECTION should end in a newline. That terminal newline is not
2284
+ folded or otherwise ellipsis does not appear.
2285
+ SECTION should be unfolded."
2286
+ (let* ((start (singular-section-start section))
2287
+ ;; do not make trailing newline invisible
2288
+ (end (1- (singular-section-end section)))
2289
+ invisibility-overlay)
2290
+ ;; create new overlay and add properties
2291
+ (setq invisibility-overlay (make-overlay start end))
2292
+ ;; mark them as invisibility overlays
2293
+ (overlay-put invisibility-overlay 'singular-invisible t)
2294
+ ;; set invisible properties
2295
+ (overlay-put invisibility-overlay 'invisible 'singular-interactive-mode)
2296
+ ;; evaporate empty invisibility overlays
2297
+ (overlay-put invisibility-overlay 'evaporate t)))
2298
+
2299
+ (defun singular-emacs-folding-unfold-internal (section &optional invisibility-overlay)
2300
+ "Unfold section SECTION.
2301
+ SECTION should be folded.
2302
+ If optional argument INVISIBILITY-OVERLAY is non-nil it should be the
2303
+ invisibility overlay of the section to unfold."
2304
+ (let ((invisibility-overlay
2305
+ (or invisibility-overlay
2306
+ (singular-emacs-folding-foldedp-internal section))))
2307
+ ;; to keep number of overlays low we delete it
2308
+ (delete-overlay invisibility-overlay)))
2309
+
2310
+ (defun singular-emacs-folding-foldedp-internal (section)
2311
+ "Returns non-nil iff SECTION is folded.
2312
+ More specifically, returns the invisibility overlay if there is one.
2313
+ Narrowing has no effect on this function."
2314
+ (let* ((start (singular-section-start section))
2315
+ (overlays (overlays-at start))
2316
+ invisibility-overlay)
2317
+ ;; check for invisibility overlay
2318
+ (while (and overlays (not invisibility-overlay))
2319
+ (if (overlay-get (car overlays) 'singular-invisible)
2320
+ (setq invisibility-overlay (car overlays))
2321
+ (setq overlays (cdr overlays))))
2322
+ invisibility-overlay))
2323
+ ;;}}}
2324
+
2325
+ ;;{{{ Folding sections for XEmacs
2326
+
2327
+ ;; Note:
2328
+ ;;
2329
+ ;; For XEmacs, we use extents to hide text (so-called "invisibility
2330
+ ;; extents"). In addition to their `invisible' property, they have the
2331
+ ;; `singular-invisible' property set. To ignore invisible text we use the
2332
+ ;; variable `line-move-ignore-invisible' which works quite well.
2333
+
2334
+ (defun singular-xemacs-folding-fold-internal (section)
2335
+ "Fold section SECTION.
2336
+ SECTION should end in a newline. That terminal newline is not
2337
+ folded or otherwise ellipsis does not appear.
2338
+ SECTION should be unfolded."
2339
+ (let* ((start (singular-section-start section))
2340
+ ;; do not make trailing newline invisible
2341
+ (end (1- (singular-section-end section)))
2342
+ invisibility-extent)
2343
+ ;; create new extent and add properties
2344
+ (setq invisibility-extent (make-extent start end))
2345
+ ;; mark them as invisibility extents
2346
+ (set-extent-property invisibility-extent 'singular-invisible t)
2347
+ ;; set invisible properties
2348
+ (set-extent-property invisibility-extent 'invisible 'singular-interactive-mode)))
2349
+
2350
+ (defun singular-xemacs-folding-unfold-internal (section &optional invisibility-extent)
2351
+ "Unfold section SECTION.
2352
+ SECTION should be folded.
2353
+ If optional argument INVISIBILITY-EXTENT is non-nil it should be the
2354
+ invisibility extent of the section to unfold."
2355
+ (let ((invisibility-extent
2356
+ (or invisibility-extent
2357
+ (singular-xemacs-folding-foldedp-internal section))))
2358
+ ;; to keep number of extents low we delete it
2359
+ (delete-extent invisibility-extent)))
2360
+
2361
+ (defun singular-xemacs-folding-foldedp-internal (section)
2362
+ "Returns non-nil iff SECTION is folded.
2363
+ More specifically, returns the invisibility extent if there is one.
2364
+ Narrowing has no effect on this function."
2365
+ ;; do not try to use `extent-at' at this point. `extent-at' does not
2366
+ ;; return extents outside narrowed text.
2367
+ (let* ((start (singular-section-start section))
2368
+ (invisibility-extent (map-extents
2369
+ (function (lambda (ext args) ext))
2370
+ nil start start nil nil 'singular-invisible)))
2371
+ invisibility-extent))
2372
+ ;;}}}
2373
+
2374
+ ;;{{{ Online help
2375
+
2376
+ ;; Note:
2377
+ ;;
2378
+ ;; Catching user's help commands to Singular and translating them to calls
2379
+ ;; to `info' is quite a difficult task due to the asynchronous nature of
2380
+ ;; communication with Singular. We use an heuristic approach which should
2381
+ ;; work in most cases:
2382
+ ;;
2383
+ ;; - `singular-help-pre-input-filter' scans user's input for help commands.
2384
+ ;; If user issues a help command the filter sets a time stamp and passes
2385
+ ;; the input unchanged to Singular.
2386
+ ;; - Singular receives the help command and barfs that it could not process
2387
+ ;; it. We call that error message "Singular's response". That response
2388
+ ;; in particular contains the help topic the user requested. If the
2389
+ ;; response for some reasons is not recognized and filtered in the later
2390
+ ;; steps the user gets some reasonable response on her command that way.
2391
+ ;; - `singular-help-pre-output-filter' on each output from Singular checks
2392
+ ;; (using the time stamp set by `singular-help-pre-input-filter') whether
2393
+ ;; the user issued a help command at most one second ago. If so,
2394
+ ;; `singular-help-pre-output-filter' starts checking Singular's output
2395
+ ;; for the response on the help command. If it finds one it remembers
2396
+ ;; the help topic in `singular-help-topic' and removes the response from
2397
+ ;; Singular's output.
2398
+ ;; There is some extra magic built into the filter to handle responses
2399
+ ;; from Singular which are received by emacs not in one string but in
2400
+ ;; more than one piece (we call that pending output).
2401
+ ;; - As the last step step of this procedure, `singular-post-output-filter'
2402
+ ;; fires up an Info buffer using `singular-help' if the variable
2403
+ ;; `singular-help-topic' is non-nil. This step is separated from the
2404
+ ;; previous one since joining both leads to some trouble in point
2405
+ ;; management. This is mainly due to the fact that `singular-help' opens
2406
+ ;; a new window.
2407
+ ;;
2408
+ ;; To show some online help, the online help manual has to be available, of
2409
+ ;; course. There is a number of possibilities for the user to set the file
2410
+ ;; name of the manual explicitly, as described in the documentation string
2411
+ ;; to `singular-help'. But in general the file name should be recognized
2412
+ ;; automatically by Singular interactive mode. For that to work, Singular
2413
+ ;; prints the file name when it comes up and option `--emacs' is specified.
2414
+ ;; This is recognized by `singular-scan-header-pre-output-filter' which
2415
+ ;; sets the variable `singular-help-file-name' accordingly. For more
2416
+ ;; information one should refer to the `Header scanning ...' folding.
2417
+ ;;
2418
+ ;; Another variable which needs to be set for proper operation is
2419
+ ;; `singular-help-topics-alist' for completion of help topics and for
2420
+ ;; recognition of help topics around point. It is no error for this
2421
+ ;; variable not to be set: simply the features do not work then.
2422
+
2423
+ ;; this `require' is necessary since we use functions from the Info package
2424
+ ;; which are not declared as `autoload'
2425
+ (require 'info)
2426
+
2427
+ (defcustom singular-help-same-window 'default
2428
+ "*Specifies how to open the window for Singular online help.
2429
+ If this variable equals t, Singular online help comes up in the selected
2430
+ window.
2431
+ If this variable equals nil, Singular online help comes up in another
2432
+ window.
2433
+ If this variable equals neither t nor nil, the standard Emacs behaviour to
2434
+ open the Info buffer is adopted (which very much depends on the settings of
2435
+ `same-window-buffer-names')."
2436
+ :initialize 'custom-initialize-default
2437
+ :type '(choice (const :tag "This window" t)
2438
+ (const :tag "Other window" nil)
2439
+ (const :tag "Default" default))
2440
+ :group 'singular-interactive-miscellaneous)
2441
+
2442
+ (defcustom singular-help-explicit-file-name nil
2443
+ "*Specifies the file name of the Singular online manual.
2444
+ If non-nil, used as file name of the Singular online manual.
2445
+
2446
+ This variable should be customized only if all other attempts of Singular
2447
+ interactive mode fail to determine the file name of the Singular online
2448
+ manual. For more information one should refer to the `singular-help'
2449
+ function."
2450
+ :initialize 'custom-initialize-default
2451
+ :type '(choice (const nil) file)
2452
+ :group 'singular-interactive-miscellaneous)
2453
+
2454
+ (defvar singular-help-file-name nil
2455
+ "File name of the Singular online manual.
2456
+ This variable should not be modified by the user.
2457
+
2458
+ This variable is buffer-local.")
2459
+
2460
+ (defconst singular-help-fall-back-file-name "singular.info"
2461
+ "Fall-back file name of the Singular online manual.
2462
+ This variable is used if the file name of the Singular online manual cannot
2463
+ be determined otherwise.")
2464
+
2465
+ (defvar singular-help-time-stamp '(0 0)
2466
+ "The time stamp that is set when the user issues a help command.
2467
+
2468
+ This variable is buffer-local.")
2469
+
2470
+ (defvar singular-help-response-pending nil
2471
+ "If non-nil, Singular's response has not been completely received.
2472
+
2473
+ This variable is buffer-local.")
2474
+
2475
+ (defvar singular-help-topic nil
2476
+ "If non-nil, contains help topic to show in post output filter.
2477
+
2478
+ This variable is buffer-local.")
2479
+
2480
+ (defconst singular-help-command-regexp "^\\s-*\\(help\\|\?\\)"
2481
+ "Regular expression to match Singular help commands.")
2482
+
2483
+ (defconst singular-help-response-line-1
2484
+ "^// \\*\\* Your help command could not be executed\\. Use\n"
2485
+ "Regular expression that matches the first line of Singular's response.")
2486
+
2487
+ (defconst singular-help-response-line-2
2488
+ "^// \\*\\* C-h C-s \\(.*\\)\n"
2489
+ "Regular expression that matches the second line of Singular's response.
2490
+ First subexpression matches help topic.")
2491
+
2492
+ (defconst singular-help-response-line-3
2493
+ "^// \\*\\* to enter the Singular online help\\. For general\n"
2494
+ "Regular expression that matches the third line of Singular's response.")
2495
+
2496
+ (defconst singular-help-response-line-4
2497
+ "^// \\*\\* information on Singular running under Emacs, type C-h m\\.\n"
2498
+ "Regular expression that matches the fourth line of Singular's response.")
2499
+
2500
+ (defun singular-help-pre-input-filter (input)
2501
+ "Check user's input for help commands.
2502
+ Sets time stamp if one is found. Passes user's input on to Singular
2503
+ unchanged."
2504
+ (if (string-match singular-help-command-regexp input)
2505
+ (setq singular-help-time-stamp (current-time)))
2506
+ ;; return nil so that input passes unchanged
2507
+ nil)
2508
+
2509
+ (defun singular-help-pre-output-filter (output)
2510
+ "Check for Singular's response on a help command.
2511
+ Removes it and sets `singular-help-topic' accordingly."
2512
+ ;; check first
2513
+ ;; - whether a help statement has been issued at most one second ago, or
2514
+ ;; - whether there is a pending response.
2515
+ ;; Only if one of these conditions is met we go on and check text for a
2516
+ ;; response on a help command. Checking uncoditionally every piece of
2517
+ ;; output would be far too expensive.
2518
+ ;; If check fails nil is returned, what is exactly what we need for the
2519
+ ;; filter.
2520
+ (if (or (= (cadr (current-time)) (cadr singular-help-time-stamp))
2521
+ singular-help-response-pending)
2522
+ ;; if response is pending for more than five seconds, give up
2523
+ (if (and singular-help-response-pending
2524
+ (> (singular-time-stamp-difference (current-time) singular-help-time-stamp) 5))
2525
+ ;; this command returns nil, what is exactly what we need for the filter
2526
+ (setq singular-help-response-pending nil)
2527
+ ;; go through output, removing the response. If there is a
2528
+ ;; pending response we nevertheless check for all lines, not only
2529
+ ;; for the pending one. At last, pending responses should not
2530
+ ;; occur to often.
2531
+ (when (string-match singular-help-response-line-1 output)
2532
+ (setq output (replace-match "" t t output))
2533
+ (setq singular-help-response-pending t))
2534
+ (when (string-match singular-help-response-line-2 output)
2535
+ ;; after all, we found what we are looking for
2536
+ (setq singular-help-topic (substring output (match-beginning 1) (match-end 1)))
2537
+ (setq output (replace-match "" t t output))
2538
+ (setq singular-help-response-pending t))
2539
+ (when (string-match singular-help-response-line-3 output)
2540
+ (setq output (replace-match "" t t output))
2541
+ (setq singular-help-response-pending t))
2542
+ (when (string-match singular-help-response-line-4 output)
2543
+ (setq output (replace-match "" t t output))
2544
+ ;; we completely removed the help from output!
2545
+ (setq singular-help-response-pending nil))
2546
+
2547
+ ;; return modified OUTPUT
2548
+ output)))
2549
+
2550
+ (defun singular-help-post-output-filter (&rest ignore)
2551
+ "Call `singular-help' if `singular-help-topic' is non-nil."
2552
+ (when singular-help-topic
2553
+ (save-excursion
2554
+ (singular-help singular-help-topic))
2555
+ (setq singular-help-topic nil)))
2556
+
2557
+ (defvar singular-help-topic-history nil
2558
+ "History of help topics used as arguments to `singular-help'.")
2559
+
2560
+ (defun singular-help (&optional help-topic)
2561
+ "Show help on HELP-TOPIC in Singular online manual.
2562
+
2563
+ The file name of the Singular online manual is determined in the following
2564
+ manner:
2565
+ o if the \(customizable) variable `singular-help-explicit-file-name' is
2566
+ non-nil, it is used as file name;
2567
+ o otherwise, if the variable `singular-help-file-name' is non-nil, is is
2568
+ used as file name. This variable should be set by Singular interactive
2569
+ mode itself, but there may be instances where this fails. Anyway, it
2570
+ should be not set by the user.
2571
+ o otherwise, if the environment variable SINGULAR_INFO_FILE is set, it is
2572
+ used as file name;
2573
+ o otherwise, the constant `singular-help-fall-back-file-name' is used
2574
+ as file name."
2575
+ (interactive
2576
+ (list (completing-read "Help topic: " singular-help-topics-alist
2577
+ nil nil nil 'singular-help-topic-history)))
2578
+
2579
+ ;; get help file and topic
2580
+ (let ((help-file-name (or singular-help-explicit-file-name
2581
+ singular-help-file-name
2582
+ (getenv "SINGULAR_INFO_FILE")
2583
+ singular-help-fall-back-file-name))
2584
+ (help-topic (cond ((or (null help-topic)
2585
+ (string= help-topic ""))
2586
+ "Top")
2587
+ ;; try to get the real topic from the alist.
2588
+ ;; It's OK if the alist is empty.
2589
+ ((cdr (assoc help-topic
2590
+ singular-help-topics-alist)))
2591
+ (t help-topic)))
2592
+ (continue t))
2593
+
2594
+ ;; pop to Info buffer
2595
+ (singular-pop-to-buffer singular-help-same-window "*info*")
2596
+
2597
+ ;; test whether we are already in Singular's online manual
2598
+ (unless (and (boundp 'Info-current-file)
2599
+ (equal Info-current-file help-file-name))
2600
+ ;; jump to Singular's top node
2601
+ (condition-case signal
2602
+ (Info-find-node help-file-name "Top")
2603
+ ;; in case of an error jump to info directory
2604
+ (error
2605
+ (Info-directory)
2606
+ ;; if we have been called interactively we pass the error down,
2607
+ ;; otherwise we assumes that we have been called from a hook and
2608
+ ;; call `singular-error'
2609
+ (if (interactive-p)
2610
+ (signal (car signal) (cdr signal))
2611
+ (singular-error "Singular online manual %s not found"
2612
+ help-file-name))
2613
+ ;; do not continue
2614
+ (setq continue nil))))
2615
+
2616
+ (when continue
2617
+ ;; jump to desired node
2618
+ (condition-case signal
2619
+ (Info-goto-node help-topic)
2620
+ ;; in case of an error jump to Singular's top node
2621
+ (error
2622
+ (Info-goto-node "Top")
2623
+ ;; if we have been called interactively we pass the error down,
2624
+ ;; otherwise we assumes that we have been called from a hook and
2625
+ ;; call `singular-error'
2626
+ (if (interactive-p)
2627
+ (signal (car signal) (cdr signal))
2628
+ (singular-error "Singular help topic %s not found"
2629
+ help-topic)))))))
2630
+
2631
+ ;; This might not be the best place for singular-example, but this function
2632
+ ;; is some kind of singular help, so the place is not too bad.
2633
+ ;; Note: We use singular-help-topic-history for singular-example, too
2634
+ (defun singular-example (&optional command)
2635
+ "Show Singular example on COMMAND."
2636
+ (interactive
2637
+ (list (completing-read "Example for: " singular-examples-alist
2638
+ nil nil nil 'singular-help-topic-history)))
2639
+ (let ((process (singular-process))
2640
+ (string (concat "example " command ";")))
2641
+ (singular-input-filter process string)
2642
+ (singular-send-string process string)))
2643
+
2644
+ (defun singular-help-init ()
2645
+ "Initialize online help support for Singular interactive mode.
2646
+
2647
+ This function is called at mode initialization time."
2648
+ (make-local-variable 'singular-help-file-name)
2649
+ (make-local-variable 'singular-help-time-stamp)
2650
+ (make-local-variable 'singular-help-response-pending)
2651
+ (make-local-variable 'singular-help-topic)
2652
+ (add-hook 'singular-pre-input-filter-functions 'singular-help-pre-input-filter)
2653
+ (add-hook 'singular-pre-output-filter-functions 'singular-help-pre-output-filter)
2654
+ (add-hook 'singular-post-output-filter-functions 'singular-help-post-output-filter))
2655
+ ;;}}}
2656
+
2657
+ ;;{{{ Singular commands, help topics and standard libraries alists
2658
+ (defvar singular-commands-alist nil
2659
+ "An alist containing all Singular commands to complete.
2660
+
2661
+ This variable is buffer-local.")
2662
+
2663
+ (defvar singular-help-topics-alist nil
2664
+ "An alist containing all Singular help topics to complete.
2665
+
2666
+ This variable is buffer-local.")
2667
+
2668
+ (defvar singular-standard-libraries-with-categories nil
2669
+ "A list containing all Singular standard library names and their category.
2670
+
2671
+ This variable is buffer-local.")
2672
+
2673
+ (defvar singular-standard-libraries-alist nil
2674
+ "An alist containing all Singular standard library names.
2675
+ This variable is set automatically by `singular-menu-install-libraries'
2676
+ using the value of `singular-standard-libraries-with-categories'.
2677
+
2678
+ This variable is buffer-local.")
2679
+ ;;}}}
2680
+
2681
+ ;;{{{ Scanning of header and handling of emacs home directory
2682
+ ;;
2683
+ ;; Scanning of header
2684
+ ;;
2685
+ (defconst singular-scan-header-emacs-home-regexp "^// \\*\\* EmacsDir: \\(.+\\)\n"
2686
+ "Regular expression matching the location of emacs home in Singular
2687
+ header.")
2688
+
2689
+ (defconst singular-scan-header-info-file-regexp "^// \\*\\* InfoFile: \\(.+\\)\n"
2690
+ "Regular expression matching the location of Singular info file in
2691
+ Singular header.")
2692
+
2693
+ (defconst singular-scan-header-time-stamp 0
2694
+ "A time stamp set by singular-scan-header.
2695
+
2696
+ This variable is buffer-local.")
2697
+
2698
+ (defvar singular-scan-header-scan-for '()
2699
+ "List of things to scan for in Singular header.
2700
+ If `singular-scan-header-pre-output-filter' finds one thing in the current
2701
+ output, it removes the corresponding value from the list.
2702
+ If this variable gets nil, `singular-scan-header-pre-output-filter' is
2703
+ removed from the pre-output-filter.
2704
+ This variable is initialized in `singular-scan-header-init'. Possible
2705
+ values of this list are up to now `help-file' and `emacs-home'.
2706
+
2707
+ This variable is buffer-local.")
2708
+
2709
+ (defun singular-scan-header-got-emacs-home ()
2710
+ "Load Singular completion and libraries files.
2711
+ Assumes that `singular-emacs-home-directory' is set to the appropriate
2712
+ value and loads the files \"cmd-cmpl.el\", \"hlp-cmpl.el\", \"ex-cmpl.el\",
2713
+ and \"lib-cmpl.el\".
2714
+ On success calls `singular-menu-install-libraries'."
2715
+ (or (load (singular-expand-emacs-file-name "cmd-cmpl.el" t) t t t)
2716
+ (message "Can't find command completion file! Command completion disabled."))
2717
+ (or (load (singular-expand-emacs-file-name "hlp-cmpl.el" t) t t t)
2718
+ (message "Can't find help topic completion file! Help completion disabled."))
2719
+ (or (load (singular-expand-emacs-file-name "ex-cmpl.el" t) t t t)
2720
+ (message "Can't find examples completion file! Examples completion disabled."))
2721
+ (if (load (singular-expand-emacs-file-name "lib-cmpl.el" t) t t t)
2722
+ (singular-menu-install-libraries)
2723
+ (message "Can't find library index file!")))
2724
+
2725
+
2726
+ (defun singular-scan-header-pre-output-filter (output)
2727
+ "Filter function for hook `singular-pro-output-filter-functions'.
2728
+ Scans the Singular header for special markers using the regexps
2729
+ `singular-scan-header-info-file-regexp' and
2730
+ `singular-scan-header-emacs-home-regexp', removes them, loads the
2731
+ completion files, the library-list file, calls
2732
+ `singular-menu-install-libraries' and sets `singular-help-file-name'.
2733
+ Removes itself from the hook if all special markers were found or if it has
2734
+ been searching for more than 20 seconds."
2735
+ (singular-debug 'interactive (message "scanning header"))
2736
+ (let ((changed nil))
2737
+
2738
+ ;; Search for emacs home directory
2739
+ (when (string-match singular-scan-header-emacs-home-regexp output)
2740
+ (let ((emacs-home (substring output (match-beginning 1) (match-end 1))))
2741
+ (singular-debug 'interactive
2742
+ (message "scan header: emacs home path found"))
2743
+ ;; in any case, remove marker from output
2744
+ (setq output (replace-match "" t t output))
2745
+ (setq changed t)
2746
+ ;; if not already done, do action an singular-emacs-home
2747
+ (when (memq 'emacs-home singular-scan-header-scan-for)
2748
+ (singular-debug 'interactive (message "scan header: initializing emacs-home-directory"))
2749
+ (setq singular-scan-header-scan-for (delq 'emacs-home singular-scan-header-scan-for))
2750
+ (setq singular-emacs-home-directory emacs-home)
2751
+ (singular-scan-header-got-emacs-home))))
2752
+
2753
+ ;; Search for Singular info file
2754
+ (when (string-match singular-scan-header-info-file-regexp output)
2755
+ (let ((file-name (substring output (match-beginning 1) (match-end 1))))
2756
+ (singular-debug 'interactive
2757
+ (message "scan header: singular.info path found"))
2758
+ ;; in any case, remove marker from output
2759
+ (setq output (replace-match "" t t output))
2760
+ (setq changed t)
2761
+ ;; if not already done, do action on help-file-name
2762
+ (when (memq 'info-file singular-scan-header-scan-for)
2763
+ (singular-debug 'interactive (message "scan header: initializing help-file-name"))
2764
+ (setq singular-scan-header-scan-for (delq 'info-file singular-scan-header-scan-for))
2765
+ (setq singular-help-file-name file-name))))
2766
+
2767
+ ;; Remove from hook if everything is found or if we already waited
2768
+ ;; too long.
2769
+ (if (or (eq singular-scan-header-scan-for nil)
2770
+ (> (singular-time-stamp-difference (current-time) singular-scan-header-time-stamp) 20))
2771
+ (remove-hook 'singular-pre-output-filter-functions 'singular-scan-header-pre-output-filter))
2772
+
2773
+ ;; Return new output string if we changed it, nil otherwise
2774
+ (and changed output)))
2775
+
2776
+ (defun singular-scan-header-init ()
2777
+ "Initialize scanning of header for Singular interactive mode.
2778
+
2779
+ This function is called by `singular-exec'."
2780
+ (singular-debug 'interactive (message "Initializing scan-header"))
2781
+ (set (make-local-variable 'singular-scan-header-time-stamp) (current-time))
2782
+ (set (make-local-variable 'singular-scan-header-scan-for) '())
2783
+
2784
+ (make-local-variable 'singular-emacs-home-directory)
2785
+ ;; if singular-emacs-home is set try to load the completion files.
2786
+ ;; Otherwise set marker that we still have to search for it.
2787
+ (if singular-emacs-home-directory
2788
+ (singular-scan-header-got-emacs-home)
2789
+ (setq singular-scan-header-scan-for (append singular-scan-header-scan-for '(emacs-home))))
2790
+
2791
+ ;; Up to now this seems to be the best place to initialize
2792
+ ;; `singular-help-file-name' since singular-help gets initialized
2793
+ ;; only on mode start-up, not on Singular start-up
2794
+ ;;
2795
+ ;; if singular-help-file-name is not set, mark, that we have to scan for it
2796
+ (make-local-variable 'singular-help-file-name)
2797
+ (or singular-help-file-name
2798
+ (setq singular-scan-header-scan-for (append singular-scan-header-scan-for '(info-file))))
2799
+
2800
+ (add-hook 'singular-pre-output-filter-functions 'singular-scan-header-pre-output-filter))
2801
+
2802
+ (defun singular-scan-header-exit ()
2803
+ "Reinitialize scanning of header for Singular interactive mode.
2804
+
2805
+ This function is called by `singular-exit-sentinel'."
2806
+ ;; unset variables so that all subsequent calls of Singular will
2807
+ ;; scan the header.
2808
+ (singular-debug 'interactive (message "Deinitializing scan-header"))
2809
+ (setq singular-emacs-home-directory nil)
2810
+ (setq singular-help-file-name nil))
2811
+
2812
+ ;;
2813
+ ;; handling of emacs home directory
2814
+ ;;
2815
+ ;; A note on `singular-emacs-home-directory': If this variable is set
2816
+ ;; before singular.el is evaluated, the header of the first Singular
2817
+ ;; started is NOT searched for the singular-emacs-home-directory.
2818
+ ;; Anyhow, all subsequent calls of Singular will scan the header
2819
+ ;; regardless of the initial state of this variable. (The exit-sentinel
2820
+ ;; will set this variable back to nil.)
2821
+ ;; See also `singular-scan-header-exit'.
2822
+ (defvar singular-emacs-home-directory nil
2823
+ "Path to the emacs sub-directory of Singular as string.
2824
+ `singular-scan-header-pre-output-filter' searches the Singular header for
2825
+ the path and sets this variable to the corresponding value.
2826
+ Its value is redefined on every start of Singular.
2827
+
2828
+ This variable is buffer-local.")
2829
+
2830
+ (defun singular-expand-emacs-file-name (file &optional noerror)
2831
+ "Add absolute path of emacs home directory.
2832
+ Adds the content of `singular-emacs-home-directory' to the string FILE.
2833
+ If `singular-emacs-home-directory' is nil, return nil and signal
2834
+ an error unless optional argument NOERROR is not nil."
2835
+ (if singular-emacs-home-directory
2836
+ (concat singular-emacs-home-directory
2837
+ (if (memq (aref singular-emacs-home-directory
2838
+ (1- (length singular-emacs-home-directory)))
2839
+ '(?/ ?\\))
2840
+ "" "/")
2841
+ file)
2842
+ (if noerror
2843
+ nil
2844
+ (error "Variable singular-emacs-home-directory not set"))))
2845
+ ;;}}}
2846
+
2847
+ ;;{{{ Filename, Command, and Help Completion
2848
+ (defun singular-completion-init ()
2849
+ "Initialize completion for Singular interactive mode.
2850
+ Initializes completion of file names, commands, examples, and help topics.
2851
+
2852
+ This function is called by `singular-exec'."
2853
+ (singular-debug 'interactive (message "Initializing completion"))
2854
+ (set (make-local-variable 'singular-commands-alist) nil)
2855
+ (set (make-local-variable 'singular-examples-alist) nil)
2856
+ (set (make-local-variable 'singular-help-topics-alist) nil))
2857
+
2858
+ (defun singular-completion-do (pattern beg end completion-alist)
2859
+ "Try completion on string PATTERN using alist COMPLETION-ALIST.
2860
+ Inserts completed version of PATTERN as new text between BEG and END.
2861
+ Assumes the COMPLETION-ALIST is not nil."
2862
+ (let ((completion (try-completion pattern completion-alist)))
2863
+ (cond ((eq completion t)
2864
+ (message "[Sole completion]")) ;; nothing to complete
2865
+ ((null completion) ;; no completion found
2866
+ (message "Can't find completion for \"%s\"" pattern)
2867
+ (ding))
2868
+ ((not (string= pattern completion))
2869
+ (delete-region beg end)
2870
+ (insert completion))
2871
+ (t
2872
+ (message "Making completion list...")
2873
+ (let ((list (all-completions pattern
2874
+ completion-alist)))
2875
+ (with-output-to-temp-buffer "*Completions*"
2876
+ (display-completion-list list)))
2877
+ (message "Making completion list...%s" "done")))))
2878
+
2879
+ (defun singular-dynamic-complete ()
2880
+ "Dynamic complete word before point.
2881
+ Performs file name completion if point is inside a string.
2882
+ Performs completion of Singular help topics if point is at the end of a
2883
+ help command (\"help\" or \"?\").
2884
+ Performs completion of Singular examples if point is at the end of an
2885
+ example command (\"example\").
2886
+ Otherwise performs completion of Singular commands."
2887
+ (interactive)
2888
+ ;; Check if we are inside a string. The search is done back to the
2889
+ ;; process-mark which should be the beginning of the current input.
2890
+ ;; No check at this point whether there is a process!
2891
+ (if (save-excursion
2892
+ (nth 3 (parse-partial-sexp (singular-process-mark) (point))))
2893
+ ;; then: inside string, thus expand filename
2894
+ (comint-dynamic-complete-as-filename)
2895
+ ;; else: expand command or help
2896
+ (let ((end (point))
2897
+ (post-prompt (save-excursion
2898
+ (beginning-of-line)
2899
+ (singular-prompt-skip-forward)))
2900
+ beg)
2901
+ (cond
2902
+ ((save-excursion
2903
+ (goto-char post-prompt)
2904
+ (looking-at "[ \t]*\\([\\?]\\|help \\)[ \t]*\\(.*\\)"))
2905
+ ;; then: help completion
2906
+ (if singular-help-topics-alist
2907
+ (singular-completion-do (match-string 2) (match-beginning 2)
2908
+ end singular-help-topics-alist)
2909
+ (message "Completion of Singular help topics disabled.")
2910
+ (ding)))
2911
+ ((save-excursion
2912
+ (goto-char post-prompt)
2913
+ (looking-at "[ \t]*\\(example \\)[ \t]*\\(.*\\)"))
2914
+ ;; then: example completion
2915
+ (if singular-examples-alist
2916
+ (singular-completion-do (match-string 2) (match-beginning 2)
2917
+ end singular-examples-alist)
2918
+ (message "Completion of Singular examples disabled.")
2919
+ (ding)))
2920
+ (t
2921
+ ;; else: command completion
2922
+ (save-excursion
2923
+ (skip-chars-backward "a-zA-Z0-9")
2924
+ (setq beg (point)))
2925
+ (if singular-commands-alist
2926
+ (singular-completion-do (buffer-substring beg end) beg
2927
+ end singular-commands-alist)
2928
+ (message "Completion of Singular commands disabled.")
2929
+ (ding)))))))
2930
+ ;;}}}
2931
+
2932
+ ;;{{{ Debugging filters
2933
+ (defun singular-debug-pre-input-filter (string)
2934
+ "Display STRING and some markers in mini-buffer."
2935
+ (singular-debug 'interactive-filter
2936
+ (message "Pre-input filter: %s (li %S ci %S lo %S co %S)"
2937
+ (singular-debug-format string)
2938
+ (marker-position singular-last-input-section-start)
2939
+ (marker-position singular-current-input-section-start)
2940
+ (marker-position singular-last-output-section-start)
2941
+ (marker-position singular-current-output-section-start)))
2942
+ nil)
2943
+
2944
+ (defun singular-debug-post-input-filter (beg end)
2945
+ "Display BEG, END, and some markers in mini-buffer."
2946
+ (singular-debug 'interactive-filter
2947
+ (message "Post-input filter: (beg %S end %S) (li %S ci %S lo %S co %S)"
2948
+ beg end
2949
+ (marker-position singular-last-input-section-start)
2950
+ (marker-position singular-current-input-section-start)
2951
+ (marker-position singular-last-output-section-start)
2952
+ (marker-position singular-current-output-section-start))))
2953
+
2954
+ (defun singular-debug-pre-output-filter (string)
2955
+ "Display STRING and some markers in mini-buffer."
2956
+ (singular-debug 'interactive-filter
2957
+ (message "Pre-output filter: %s (li %S ci %S lo %S co %S)"
2958
+ (singular-debug-format string)
2959
+ (marker-position singular-last-input-section-start)
2960
+ (marker-position singular-current-input-section-start)
2961
+ (marker-position singular-last-output-section-start)
2962
+ (marker-position singular-current-output-section-start)))
2963
+ nil)
2964
+
2965
+ (defun singular-debug-post-output-filter (beg end simple-sec-start)
2966
+ "Display BEG, END, SIMPLE-SEC-START, and some markers in mini-buffer."
2967
+ (singular-debug 'interactive-filter
2968
+ (message "Post-output filter: (beg %S end %S sss %S) (li %S ci %S lo %S co %S)"
2969
+ beg end simple-sec-start
2970
+ (marker-position singular-last-input-section-start)
2971
+ (marker-position singular-current-input-section-start)
2972
+ (marker-position singular-last-output-section-start)
2973
+ (marker-position singular-current-output-section-start))))
2974
+
2975
+ (defun singular-debug-filter-init ()
2976
+ "Add debug filters to the necessary hooks.
2977
+
2978
+ This function is called at mode initialization time."
2979
+ (add-hook 'singular-pre-input-filter-functions
2980
+ 'singular-debug-pre-input-filter nil t)
2981
+ (add-hook 'singular-post-input-filter-functions
2982
+ 'singular-debug-post-input-filter nil t)
2983
+ (add-hook 'singular-pre-output-filter-functions
2984
+ 'singular-debug-pre-output-filter nil t)
2985
+ (add-hook 'singular-post-output-filter-functions
2986
+ 'singular-debug-post-output-filter nil t))
2987
+ ;;}}}
2988
+
2989
+ ;;{{{ Demo mode
2990
+
2991
+ ;; Note:
2992
+ ;;
2993
+ ;; For documentation on Singular demo mode one should refer to the doc
2994
+ ;; string of `singular-demo-load'.
2995
+ ;; Singular demo mode should have been implemented as a minor mode but it
2996
+ ;; did not seem worth it.
2997
+
2998
+ (defcustom singular-demo-chunk-regexp "\\(\n\\s *\n\\)"
2999
+ "*Regular expressions to recognize chunks of a demo file.
3000
+ If there is a subexpression specified its contents is removed after the
3001
+ chunk has been displayed.
3002
+ The default value is \"\\\\(\\n\\\\s *\\n\\\\)\" which means that chunks are
3003
+ separated by one blank line which is removed after the chunks have been
3004
+ displayed."
3005
+ :type 'regexp
3006
+ :initialize 'custom-initialize-default
3007
+ :group 'singular-demo-mode)
3008
+
3009
+ (defcustom singular-demo-print-messages t
3010
+ "*If non-nil, print message on how to continue demo mode."
3011
+ :type 'boolean
3012
+ :initialize 'custom-initialize-default
3013
+ :group 'singular-demo-mode)
3014
+
3015
+ (defcustom singular-demo-exit-on-load t
3016
+ "*If non-nil, an active demo is automatically discarded when a new one is loaded.
3017
+ Otherwise, the load is aborted with an error."
3018
+ :type 'boolean
3019
+ :initialize 'custom-initialize-default
3020
+ :group 'singular-demo-mode)
3021
+
3022
+ (defcustom singular-demo-load-directory nil
3023
+ "*Directory where demo files usually reside.
3024
+ If non-nil, this directory is offered as a starting point to search for
3025
+ demo files when `singular-demo-load' is called interactively for the first
3026
+ time. (In further calls, `singular-demo-load' offers the directory where
3027
+ the last demo file has been loaded from as starting point).
3028
+
3029
+ If this variable equals nil whatever Emacs offers by default is used as
3030
+ first-time starting point. In general, this is the directory where
3031
+ Singular has been started in."
3032
+ :type '(choice (const nil) (file))
3033
+ :initialize 'custom-initialize-default
3034
+ :group 'singular-demo-mode)
3035
+
3036
+ (defvar singular-demo-mode nil
3037
+ "Non-nil if Singular demo mode is on.
3038
+
3039
+ This variable is buffer-local.")
3040
+
3041
+ (defvar singular-demo-old-mode-name nil
3042
+ "Used to store previous `mode-name' before switching to demo mode.
3043
+
3044
+ This variable is buffer-local.")
3045
+
3046
+ (defvar singular-demo-end nil
3047
+ "Marker pointing to end of demo file.
3048
+
3049
+ This variable is buffer-local.")
3050
+
3051
+ (defvar singular-demo-last-directory nil
3052
+ "If non-nil, directory from which the last demo file has been loaded.
3053
+
3054
+ This variable is buffer-local.")
3055
+
3056
+ (defun singular-demo-load (demo-file)
3057
+ "Load demo file DEMO-FILE and enter Singular demo mode.
3058
+
3059
+ The Singular demo mode allows to step conveniently through a prepared demo
3060
+ file. The contents of the demo file is made visible and executed in
3061
+ portions called chunks. How the chunks have to be marked in the demo file
3062
+ is described below.
3063
+
3064
+ After loading the demo file with this function, \\[singular-send-or-copy-input] displays the first
3065
+ chunk of the demo file at the Singular prompt. This chunk may be modified
3066
+ \(or even deleted) and then sent to Singular entering \\[singular-send-or-copy-input] as any command
3067
+ would have been sent to Singular. The next time \\[singular-send-or-copy-input] is entered, the next
3068
+ chunk of the demo file is displayed, and so on.
3069
+
3070
+ One may interrupt this sequence and enter commands at the Singular input
3071
+ prompt as usual. As soon as \\[singular-send-or-copy-input] is entered directly after the input
3072
+ prompt, the next chunk of the demo file is displayed. Here is the exact
3073
+ algorithm how this magic works: If point is located at the very end of the
3074
+ buffer *and* immediately after Singular's last input prompt, the next chunk
3075
+ of the demo file is displayed. In particular, if there is any text after
3076
+ the last input prompt that text is sent to Singular as usual and no new
3077
+ chunks are displayed.
3078
+
3079
+ After displaying the last chunk of DEMO-FILE, Singular demo mode
3080
+ automatically terminates and normal operation is resumed. To prematurely
3081
+ exit Singular demo mode \\[singular-demo-exit] may be used.
3082
+
3083
+ DEMO-FILE should consist of regular Singular commands. Portions of text
3084
+ separated by a blank line are taken to be the chunks of the demo file.
3085
+
3086
+ There is a number of variables to configure Singular demo mode. Refer to
3087
+ the `singular-demo-mode' customization group for more information.
3088
+
3089
+ Important note: The unprocessed contents of DEMO-FILE is hidden using
3090
+ buffer narrowing. Emacs gets terribly confused when during demo mode the
3091
+ buffer is either narrowed to some other region or if the buffer is widened.
3092
+ The safest thing to do if that happens by accident is to explicitly exit
3093
+ the demo by means of \\[singular-demo-exit] and to try to resume somehow
3094
+ normal operation.
3095
+
3096
+ `singular-demo-load' runs the functions on `singular-demo-mode-enter-hook'
3097
+ just after demo mode has been entered. The functions on
3098
+ `singular-demo-mode-exit-hook' are executed after Singular demo mode has
3099
+ been exited, either prematurely or due to the end of the demo file.
3100
+ However, it its important to note that in the latter case the last chunk of
3101
+ the demo file is still waiting to be sent to Singular."
3102
+ (interactive
3103
+ (list
3104
+ (let ((demo-file-name
3105
+ (cond
3106
+ ;; Emacs
3107
+ ((eq singular-emacs-flavor 'emacs)
3108
+ (read-file-name "Load demo file: "
3109
+ (or singular-demo-last-directory
3110
+ singular-demo-load-directory)
3111
+ nil t))
3112
+ ;; XEmacs
3113
+ (t
3114
+ ;; there are some problems with the window being popped up when this
3115
+ ;; function is called from a menu. It does not display the contents
3116
+ ;; of `singular-demo-load-directory' but of `default-directory'.
3117
+ (let ((default-directory (or singular-demo-last-directory
3118
+ singular-demo-load-directory
3119
+ default-directory)))
3120
+ (read-file-name "Load demo file: "
3121
+ (or singular-demo-last-directory
3122
+ singular-demo-load-directory)
3123
+ nil t))))))
3124
+
3125
+ (setq singular-demo-last-directory (file-name-directory demo-file-name))
3126
+ demo-file-name)))
3127
+
3128
+ ;; check for running demo
3129
+ (if singular-demo-mode
3130
+ (if singular-demo-exit-on-load
3131
+ ;; silently exit running demo
3132
+ (singular-demo-exit t)
3133
+ (error "There already is a demo running, exit with `singular-demo-exit' first")))
3134
+
3135
+ ;; load new demo
3136
+ (let ((old-point-min (point-min)))
3137
+ (unwind-protect
3138
+ (progn
3139
+ (goto-char (point-max))
3140
+ (widen)
3141
+ (cond
3142
+ ;; XEmacs
3143
+ ((eq singular-emacs-flavor 'xemacs)
3144
+ ;; load file and remember its end
3145
+ (set-marker singular-demo-end
3146
+ (+ (point) (nth 1 (insert-file-contents-literally demo-file)))))
3147
+ ;; Emacs
3148
+ (t
3149
+ ;; Emacs does something like an `insert-before-markers' so
3150
+ ;; save all essential markers
3151
+ (let ((pmark-pos (marker-position (singular-process-mark)))
3152
+ (sliss-pos (marker-position singular-last-input-section-start))
3153
+ (sciss-pos (marker-position singular-current-input-section-start))
3154
+ (sloss-pos (marker-position singular-last-output-section-start))
3155
+ (scoss-pos (marker-position singular-current-output-section-start)))
3156
+
3157
+ (unwind-protect
3158
+ ;; load file and remember its end
3159
+ (set-marker singular-demo-end
3160
+ (+ (point) (nth 1 (insert-file-contents-literally demo-file))))
3161
+
3162
+ ;; restore markers.
3163
+ ;; This is unwind-protected.
3164
+ (set-marker (singular-process-mark) pmark-pos)
3165
+ (set-marker singular-last-input-section-start sliss-pos)
3166
+ (set-marker singular-current-input-section-start sciss-pos)
3167
+ (set-marker singular-last-output-section-start sloss-pos)
3168
+ (set-marker singular-current-output-section-start scoss-pos))))))
3169
+
3170
+ ;; completely hide demo file.
3171
+ ;; This is unwind-protected.
3172
+ (narrow-to-region old-point-min (point))))
3173
+
3174
+ ;; switch demo mode on
3175
+ (setq singular-demo-old-mode-name mode-name
3176
+ mode-name "Singular Demo"
3177
+ singular-demo-mode t)
3178
+ (run-hooks 'singular-demo-mode-enter-hook)
3179
+ (if singular-demo-print-messages (message "Hit RET to start demo"))
3180
+ (force-mode-line-update))
3181
+
3182
+ (defun singular-demo-exit-internal ()
3183
+ "Exit Singular demo mode.
3184
+ Recovers the old mode name, sets `singular-demo-mode' to nil, runs
3185
+ the hooks on `singular-demo-mode-exit-hook'."
3186
+ (setq mode-name singular-demo-old-mode-name
3187
+ singular-demo-mode nil)
3188
+ (run-hooks 'singular-demo-mode-exit-hook)
3189
+ (force-mode-line-update))
3190
+
3191
+ (defun singular-demo-exit (&optional no-message)
3192
+ "Prematurely exit Singular demo mode.
3193
+ Cleans up everything that is left from the demo.
3194
+ Runs the hooks on `singular-demo-mode-exit-hook'.
3195
+ Does nothing when Singular demo mode is not active."
3196
+ (interactive)
3197
+ (when singular-demo-mode
3198
+ ;; clean up hidden rest of demo file
3199
+ (let ((old-point-min (point-min))
3200
+ (old-point-max (point-max)))
3201
+ (unwind-protect
3202
+ (progn
3203
+ (widen)
3204
+ (delete-region old-point-max singular-demo-end))
3205
+ ;; this is unwind-protected
3206
+ (narrow-to-region old-point-min old-point-max)))
3207
+ (singular-demo-exit-internal)
3208
+ (or no-message
3209
+ (if singular-demo-print-messages (message "Demo exited")))))
3210
+
3211
+ (defun singular-demo-show-next-chunk ()
3212
+ "Show next chunk of demo file at input prompt.
3213
+ Assumes that Singular demo mode is active.
3214
+ Moves point to end of buffer and widenes the buffer such that the next
3215
+ chunk of the demo file becomes visible.
3216
+ Finds and removes chunk separators as specified by
3217
+ `singular-demo-chunk-regexp'.
3218
+ Leaves demo mode after showing last chunk. In that case runs hooks on
3219
+ `singular-demo-mode-exit-hook'."
3220
+ (let ((old-point-min (point-min)))
3221
+ (unwind-protect
3222
+ (progn
3223
+ (goto-char (point-max))
3224
+ (widen)
3225
+ (if (re-search-forward singular-demo-chunk-regexp singular-demo-end 'limit)
3226
+ (if (match-beginning 1)
3227
+ (delete-region (match-beginning 1) (match-end 1)))
3228
+ ;; remove trailing white-space. We may not use
3229
+ ;; `(skip-syntax-backward "-")' since newline is has no white
3230
+ ;; space syntax. The solution down below should suffice in
3231
+ ;; almost all cases ...
3232
+ (skip-chars-backward " \t\n\r\f")
3233
+ (delete-region (point) singular-demo-end)
3234
+ (singular-demo-exit-internal)))
3235
+
3236
+ ;; this is unwind-protected
3237
+ (narrow-to-region old-point-min (point)))))
3238
+
3239
+ (defun singular-demo-mode-init ()
3240
+ "Initialize variables belonging to Singular demo mode.
3241
+ Creates some buffer-local variables and the buffer-local marker
3242
+ `singular-demo-end'.
3243
+
3244
+ This function is called at mode initialization time."
3245
+ (make-local-variable 'singular-demo-mode)
3246
+ (make-local-variable 'singular-demo-mode-old-name)
3247
+ (make-local-variable 'singular-demo-mode-end)
3248
+ (if (not (and (boundp 'singular-demo-end)
3249
+ singular-demo-end))
3250
+ (setq singular-demo-end (make-marker)))
3251
+ (make-local-variable 'singular-demo-last-directory))
3252
+ ;;}}}
3253
+
3254
+ ;;{{{ Some lengthy notes on input and output
3255
+
3256
+ ;; NOT READY[so sorry]!
3257
+
3258
+ ;;}}}
3259
+
3260
+ ;;{{{ Last input and output section
3261
+ (defun singular-last-input-section (&optional no-error)
3262
+ "Return last input section.
3263
+ Returns nil if optional argument NO-ERROR is non-nil and there is no
3264
+ last input section defined, throws an error otherwise."
3265
+ (let ((last-input-start (marker-position singular-last-input-section-start))
3266
+ (last-input-end (marker-position singular-current-output-section-start)))
3267
+ (cond ((and last-input-start last-input-end)
3268
+ (singular-section-create (singular-simple-sec-at last-input-start) 'input
3269
+ last-input-start last-input-end))
3270
+ (no-error nil)
3271
+ (t (error "No last input section defined")))))
3272
+
3273
+ (defun singular-current-output-section (&optional no-error)
3274
+ "Return current output section.
3275
+ Returns nil if optional argument NO-ERROR is non-nil and there is no
3276
+ current output section defined, throws an error otherwise."
3277
+ (let ((current-output-start (marker-position singular-current-output-section-start))
3278
+ (current-output-end (save-excursion
3279
+ (save-restriction
3280
+ (widen)
3281
+ (goto-char (singular-process-mark))
3282
+ (singular-prompt-skip-backward)
3283
+ (and (bolp) (point))))))
3284
+ (cond ((and current-output-start current-output-end)
3285
+ (singular-section-create (singular-simple-sec-at current-output-start) 'output
3286
+ current-output-start current-output-end))
3287
+ (no-error nil)
3288
+ (t (error "No current output section defined")))))
3289
+
3290
+ (defun singular-last-output-section (&optional no-error)
3291
+ "Return last output section.
3292
+ Returns nil if optional argument NO-ERROR is non-nil and there is no
3293
+ last output section defined, throws an error otherwise."
3294
+ (let ((last-output-start (marker-position singular-last-output-section-start))
3295
+ (last-output-end (marker-position singular-last-input-section-start)))
3296
+ (cond ((and last-output-start last-output-end)
3297
+ (singular-section-create (singular-simple-sec-at last-output-start) 'output
3298
+ last-output-start last-output-end))
3299
+ (no-error nil)
3300
+ (t (error "No last output section defined")))))
3301
+
3302
+ (defun singular-latest-output-section (&optional no-error)
3303
+ "Return latest output section.
3304
+ This is the current output section if it is defined, otherwise the
3305
+ last output section.
3306
+ Returns nil if optional argument NO-ERROR is non-nil and there is no
3307
+ latest output section defined, throws an error otherwise."
3308
+ (or (singular-current-output-section t)
3309
+ (singular-last-output-section t)
3310
+ (if no-error
3311
+ nil
3312
+ (error "No latest output section defined"))))
3313
+ ;;}}}
3314
+
3315
+ ;;{{{ Sending input
3316
+ (defvar singular-pre-input-filter-functions nil
3317
+ "Functions to call before input is sent to process.
3318
+ These functions get one argument, a string containing the text which
3319
+ is to be sent to process. The functions should return either nil
3320
+ or a string. In the latter case the returned string replaces the
3321
+ string to be sent to process.
3322
+
3323
+ This is a buffer-local variable, not a buffer-local hook!
3324
+
3325
+ `singular-run-hook-with-arg-and-value' is used to run the functions in
3326
+ the list.")
3327
+
3328
+ (defvar singular-post-input-filter-functions nil
3329
+ "Functions to call after input is sent to process.
3330
+ These functions get two arguments BEG and END.
3331
+ If `singular-input-filter' has been called with a string as argument
3332
+ BEG and END gives the position of this string after insertion into the
3333
+ buffer.
3334
+ If `singular-input-filter' has been called with a position as argument
3335
+ BEG and END equal process mark and that position, resp.
3336
+ The functions may assume that no narrowing is in effect and may change
3337
+ point at will.
3338
+
3339
+ This hook is buffer-local.")
3340
+
3341
+ (defvar singular-current-input-section-start nil
3342
+ "Marker to the start of the current input section.
3343
+ This marker points nowhere on startup or if there is no current input
3344
+ section.
3345
+
3346
+ This variable is buffer-local.")
3347
+
3348
+ (defvar singular-last-input-section-start nil
3349
+ "Marker to the start of the last input section.
3350
+ This marker points nowhere on startup.
3351
+
3352
+ This variable is buffer-local.")
3353
+
3354
+ (defun singular-input-filter-init (pos)
3355
+ "Initialize all variables concerning input.
3356
+ POS is the position of the process mark."
3357
+ ;; localize variables not yet localized in `singular-interactive-mode'
3358
+ (make-local-variable 'singular-current-input-section-start)
3359
+ (make-local-variable 'singular-last-input-section-start)
3360
+
3361
+ ;; initialize markers
3362
+ (if (not (markerp singular-current-input-section-start))
3363
+ (setq singular-current-input-section-start (make-marker)))
3364
+ (if (not (markerp singular-last-input-section-start))
3365
+ (setq singular-last-input-section-start (make-marker))))
3366
+
3367
+ (defun singular-send-string (process string)
3368
+ "Send newline terminated STRING to to process PROCESS.
3369
+ Runs the hooks on `singular-pre-input-filter-functions' in the buffer
3370
+ associated to PROCESS. The functions get the non-terminated string."
3371
+ (let ((process-buffer (process-buffer process)))
3372
+
3373
+ ;; check whether buffer is still alive
3374
+ (if (and process-buffer (buffer-name process-buffer))
3375
+ (save-excursion
3376
+ (set-buffer process-buffer)
3377
+ (process-send-string
3378
+ process
3379
+ (concat (singular-run-hook-with-arg-and-value
3380
+ singular-pre-input-filter-functions string)
3381
+ "\n"))))))
3382
+
3383
+ (defun singular-input-filter (process string-or-pos)
3384
+ "Insert/update input from user in buffer associated to PROCESS.
3385
+ Inserts STRING-OR-POS followed by a newline at process mark if it is a
3386
+ string.
3387
+ Assumes that the input is already inserted and that it is placed
3388
+ between process mark and STRING-OR-POS if the latter is a position.
3389
+ Inserts a newline after STRING-OR-POS.
3390
+
3391
+ Takes care off:
3392
+ - current buffer as well as point and restriction in buffer associated
3393
+ with process, even against non-local exits.
3394
+ Updates:
3395
+ - process mark;
3396
+ - current and last sections;
3397
+ - simple sections;
3398
+ - mode line.
3399
+
3400
+ Runs the hooks on `singular-pre-input-filter-functions' and
3401
+ `singular-post-input-filter-functions'.
3402
+
3403
+ For a more detailed descriptions of the input filter, the markers it
3404
+ sets, and input filter functions refer to the section \"Some lengthy
3405
+ notes on input and output\" in singular.el."
3406
+ (let ((process-buffer (process-buffer process)))
3407
+
3408
+ ;; check whether buffer is still alive
3409
+ (if (and process-buffer (buffer-name process-buffer))
3410
+ (let ((old-buffer (current-buffer))
3411
+ (old-pmark (marker-position (process-mark process)))
3412
+ old-point old-point-min old-point-max)
3413
+ (unwind-protect
3414
+ (let (simple-sec-start)
3415
+ (set-buffer process-buffer)
3416
+ ;; the following lines are not protected since the
3417
+ ;; unwind-forms refer the variables being set here
3418
+ (setq old-point (point-marker)
3419
+ old-point-min (point-min-marker)
3420
+ old-point-max (point-max-marker)
3421
+
3422
+ ;; get end of last simple section (equals start of
3423
+ ;; current)
3424
+ simple-sec-start (singular-simple-sec-last-end-position))
3425
+
3426
+ ;; prepare for insertion
3427
+ (widen)
3428
+ (set-marker-insertion-type old-point t)
3429
+ (set-marker-insertion-type old-point-max t)
3430
+
3431
+ ;; insert string at process mark and advance process
3432
+ ;; mark after insertion. If it not a string simply
3433
+ ;; jump to desired position and insrt a newline.
3434
+ (if (stringp string-or-pos)
3435
+ (progn
3436
+ (goto-char old-pmark)
3437
+ (insert string-or-pos))
3438
+ (goto-char string-or-pos))
3439
+ (insert ?\n)
3440
+ (set-marker (process-mark process) (point))
3441
+
3442
+ ;; create new simple section and update section markers
3443
+ (cond
3444
+ ((eq (singular-simple-sec-create 'input (point)) 'empty)
3445
+ nil)
3446
+ ;; a new simple section has been created ...
3447
+ ((null (marker-position singular-current-input-section-start))
3448
+ ;; ... and even a new input section has been created!
3449
+ (set-marker singular-current-input-section-start
3450
+ simple-sec-start)
3451
+ (set-marker singular-last-output-section-start
3452
+ singular-current-output-section-start)
3453
+ (set-marker singular-current-output-section-start nil)))
3454
+
3455
+ ;; run post-output hooks and force mode-line update
3456
+ (run-hook-with-args 'singular-post-input-filter-functions
3457
+ old-pmark (point)))
3458
+
3459
+ ;; restore buffer, restrictions and point
3460
+ (narrow-to-region old-point-min old-point-max)
3461
+ (set-marker old-point-min nil)
3462
+ (set-marker old-point-max nil)
3463
+ (goto-char old-point)
3464
+ (set-marker old-point nil)
3465
+ (set-buffer old-buffer))))))
3466
+ ;;}}}
3467
+
3468
+ ;;{{{ Sending input interactive
3469
+ (defcustom singular-move-on-send 'eob
3470
+ "*Where to move point before sending input to Singular.
3471
+ Should be one of:
3472
+ `eob' which means to move point to end of buffer,
3473
+ `eol' which means to move point to end of line, or
3474
+ nil which means to not move point at all."
3475
+ :type '(choice (const :tag "End of buffer" eob)
3476
+ (const :tag "End of line" eol)
3477
+ (const :tag "Do not move" nil))
3478
+ :initialize 'custom-initialize-default
3479
+ :group 'singular-interactive-miscellaneous)
3480
+
3481
+ (defun singular-get-old-input (get-section)
3482
+ "Get and return old input.
3483
+ Retrivies on a per-section base if GET-SECTION is non-nil, otherwise on a
3484
+ per-line base."
3485
+ (if get-section
3486
+ ;; get input from input section
3487
+ (let ((section (singular-section-at (point))))
3488
+ (if (eq (singular-section-type section) 'input)
3489
+ (singular-white-space-strip (singular-section-to-string section) t)
3490
+ (error "Not on an input section")))
3491
+ ;; get input from line
3492
+ (save-excursion
3493
+ (beginning-of-line)
3494
+ (singular-prompt-skip-forward)
3495
+ (let ((old-point (point)))
3496
+ (end-of-line)
3497
+ (buffer-substring old-point (point))))))
3498
+
3499
+ (defun singular-send-or-copy-input (get-section)
3500
+ "Send input to Singular.
3501
+
3502
+ The behavior of this function very much depends on the current position of
3503
+ point relative to the process mark, that is, the position, where Singular
3504
+ expects next input.
3505
+
3506
+ If point is located before process mark, old input is copied to the process
3507
+ mark. With prefix argument, the whole input section point currently is in
3508
+ is copied, without prefix argument only the current line. One should note
3509
+ that the input is *not* sent to Singular, it is only copied to the process
3510
+ mark. Another time entering \\[singular-send-or-copy-input] sends it to Singular.
3511
+
3512
+ If point is located after process mark, point is moved as determined by the
3513
+ `singular-move-on-send' variable: either it is moved to the end of the
3514
+ current line, or to the end of the buffer, or it is not moved at all. The
3515
+ default is to move point to the end of the buffer which most closely
3516
+ resembles regular terminal behaviour. At last, the text of the region
3517
+ between process mark and point is sent to Singular.
3518
+
3519
+ Any input to Singular is stored in an input history where it may be
3520
+ retrieved with \\[comint-previous-input] or \\[comint-next-input], respectively. For more information on the input
3521
+ history one should refer to the documentation of
3522
+ `singular-interactive-mode'.
3523
+
3524
+ If Singular demo mode is active and point is at process mark and if that
3525
+ position is at the end of the buffer the next chunk of the demo file is
3526
+ displayed. One should refer to the documentation of `singular-demo-load'
3527
+ for more information on Singular demo mode.
3528
+
3529
+ The Singular process should be running."
3530
+ (interactive "P")
3531
+ (let ((process (singular-process))
3532
+ (pmark (singular-process-mark)))
3533
+ (cond
3534
+ (;; check for demo mode and show next chunk if necessary
3535
+ (and singular-demo-mode
3536
+ (= (point) pmark)
3537
+ (= pmark (point-max)))
3538
+ (singular-demo-show-next-chunk))
3539
+
3540
+ (;; get old input
3541
+ (< (point) pmark)
3542
+ (let ((old-input (singular-get-old-input get-section)))
3543
+ (goto-char pmark)
3544
+ (insert old-input)))
3545
+
3546
+ (;; send input from pmark to point
3547
+ t
3548
+ ;; print message if demo mode is active. We print it before we do
3549
+ ;; anything else so that the message will not hide any further
3550
+ ;; (error) messages.
3551
+ (and singular-demo-mode
3552
+ singular-demo-print-messages
3553
+ (message "Hit RET to continue demo"))
3554
+
3555
+ ;; go to desired position
3556
+ (cond ((eq singular-move-on-send 'eol)
3557
+ (end-of-line))
3558
+ ((eq singular-move-on-send 'eob)
3559
+ (goto-char (point-max))))
3560
+
3561
+ (let* ((input (buffer-substring pmark (point))))
3562
+ ;; insert string into history
3563
+ (singular-history-insert input)
3564
+ ;; send string to process
3565
+ (singular-send-string process input)
3566
+ ;; "insert" it into buffer
3567
+ (singular-input-filter process (point)))))))
3568
+ ;;}}}
3569
+
3570
+ ;;{{{ Receiving output
3571
+ (defvar singular-pre-output-filter-functions nil
3572
+ "Functions to call before output is inserted into the buffer.
3573
+ These functions get one argument, a string containing the text sent
3574
+ from process. The functions should return either nil or a string.
3575
+ In the latter case the returned string replaces the string sent from
3576
+ process.
3577
+
3578
+ This is a buffer-local variable, not a buffer-local hook!
3579
+
3580
+ `singular-run-hook-with-arg-and-value' is used to run the functions in
3581
+ this list.")
3582
+
3583
+ (defvar singular-post-output-filter-functions nil
3584
+ "Functions to call after output is inserted into the buffer.
3585
+ These functions get three arguments BEG, END, and SIMPLE-SEC-START.
3586
+ The region between BEG and END is what has been inserted into the
3587
+ buffer.
3588
+ SIMPLE-SEC-START is the start of the simple section which has been
3589
+ created on insertion or nil if no simple section has been created.
3590
+ The functions may assume that no narrowing is in effect and may change
3591
+ point at will.
3592
+
3593
+ This hook is buffer-local.")
3594
+
3595
+ (defvar singular-current-output-section-start nil
3596
+ "Marker to the start of the current output section.
3597
+ This marker points nowhere on startup or if there is no current output
3598
+ section.
3599
+
3600
+ This variable is buffer-local.")
3601
+
3602
+ (defvar singular-last-output-section-start nil
3603
+ "Marker to the start of the last output section.
3604
+ This marker points nowhere on startup.
3605
+
3606
+ This variable is buffer-local.")
3607
+
3608
+ (defun singular-output-filter-init (pos)
3609
+ "Initialize all variables concerning output including process mark.
3610
+ Set process mark to POS."
3611
+
3612
+ ;; localize variables not yet localized in `singular-interactive-mode'
3613
+ (make-local-variable 'singular-current-output-section-start)
3614
+ (make-local-variable 'singular-last-output-section-start)
3615
+
3616
+ ;; initialize markers
3617
+ (if (not (markerp singular-current-output-section-start))
3618
+ (setq singular-current-output-section-start (make-marker)))
3619
+ (if (not (markerp singular-last-output-section-start))
3620
+ (setq singular-last-output-section-start (make-marker)))
3621
+ (set-marker (singular-process-mark) pos))
3622
+
3623
+ (defun singular-output-filter (process string)
3624
+ "Insert STRING containing output from PROCESS into its associated buffer.
3625
+ Takes care off:
3626
+ - current buffer as well as point and restriction in buffer associated
3627
+ with process, even against non-local exits.
3628
+ Updates:
3629
+ - process mark;
3630
+ - current and last sections;
3631
+ - simple sections;
3632
+ - mode line.
3633
+ Runs the hooks on `singular-pre-output-filter-functions' and
3634
+ `singular-post-output-filter-functions'.
3635
+
3636
+ For a more detailed descriptions of the output filter, the markers it
3637
+ sets, and output filter functions refer to the section \"Some lengthy
3638
+ notes on input and output\" in singular.el."
3639
+ (let ((process-buffer (process-buffer process)))
3640
+
3641
+ ;; check whether buffer is still alive
3642
+ (if (and process-buffer (buffer-name process-buffer))
3643
+ (let ((old-buffer (current-buffer))
3644
+ (old-pmark (marker-position (process-mark process)))
3645
+ old-point old-point-min old-point-max)
3646
+ (unwind-protect
3647
+ (let (simple-sec-start)
3648
+ (set-buffer process-buffer)
3649
+ ;; the following lines are not protected since the
3650
+ ;; unwind-forms refer the variables being set here
3651
+ (setq old-point (point-marker)
3652
+ old-point-min (point-min-marker)
3653
+ old-point-max (point-max-marker)
3654
+
3655
+ ;; get end of last simple section (equals start of
3656
+ ;; current)
3657
+ simple-sec-start (singular-simple-sec-last-end-position)
3658
+
3659
+ ;; get string to insert
3660
+ string (singular-run-hook-with-arg-and-value
3661
+ singular-pre-output-filter-functions
3662
+ string))
3663
+
3664
+ ;; prepare for insertion
3665
+ (widen)
3666
+ (set-marker-insertion-type old-point t)
3667
+ (set-marker-insertion-type old-point-max t)
3668
+
3669
+ ;; insert string at process mark and advance process
3670
+ ;; mark after insertion
3671
+ (goto-char old-pmark)
3672
+ (insert string)
3673
+ (set-marker (process-mark process) (point))
3674
+
3675
+ ;; create new simple section and update section markers
3676
+ (cond
3677
+ ((eq (singular-simple-sec-create 'output (point)) 'empty)
3678
+ (setq simple-sec-start nil))
3679
+ ;; a new simple section has been created ...
3680
+ ((null (marker-position singular-current-output-section-start))
3681
+ ;; ... and even a new output section has been created!
3682
+ (set-marker singular-current-output-section-start
3683
+ simple-sec-start)
3684
+ (set-marker singular-last-input-section-start
3685
+ singular-current-input-section-start)
3686
+ (set-marker singular-current-input-section-start nil)))
3687
+
3688
+ ;; run post-output hooks and force mode-line update
3689
+ (run-hook-with-args 'singular-post-output-filter-functions
3690
+ old-pmark (point) simple-sec-start)
3691
+ (force-mode-line-update))
3692
+
3693
+ ;; restore buffer, restrictions and point
3694
+ (narrow-to-region old-point-min old-point-max)
3695
+ (set-marker old-point-min nil)
3696
+ (set-marker old-point-max nil)
3697
+ (goto-char old-point)
3698
+ (set-marker old-point nil)
3699
+ (set-buffer old-buffer))))))
3700
+ ;;}}}
3701
+
3702
+ ;;{{{ Singular interactive mode
3703
+ (defun singular-interactive-mode ()
3704
+ "Major mode for interacting with Singular.
3705
+
3706
+ NOT READY [how to send input]!
3707
+ NOT READY [in particular: input history!]
3708
+
3709
+ NOT READY [multiple Singulars]!
3710
+
3711
+ \\{singular-interactive-mode-map}
3712
+
3713
+
3714
+ For \"backward compatibility\" with the terminal version of Singular there
3715
+ is some extra magic built into Singular interactive mode which catches help
3716
+ commands issued at the command prompt and executes this function instead.
3717
+ However, this magic is really not too magic and easily may be fooled. If
3718
+ this magic if fooled Singular prints some error message starting like this:
3719
+
3720
+ // ** Your help command could not be executed. ...
3721
+
3722
+ However, the most common case should be recognized: If one issues a help
3723
+ command to a non-busy Singular, where the help command comes on one line
3724
+ and is properly terminated with a semicolon. Like that:
3725
+
3726
+ help ring;
3727
+
3728
+ Customization: Entry to this mode runs the hooks on
3729
+ `singular-interactive-mode-hook'.
3730
+
3731
+ NOT READY [much more to come. See shell.el.]!"
3732
+ (interactive)
3733
+
3734
+ ;; uh-oh, we have to set `comint-input-ring-size' before we call
3735
+ ;; `comint-mode'
3736
+ (singular-history-init)
3737
+
3738
+ ;; run comint mode and do basic mode setup
3739
+ (let (comint-mode-hook)
3740
+ (comint-mode)
3741
+ (singular-comint-init))
3742
+ (setq major-mode 'singular-interactive-mode)
3743
+ (setq mode-name "Singular Interaction")
3744
+
3745
+ ;; some other initialization found in no folding
3746
+ (setq comment-start "// ")
3747
+ (setq comment-start-skip "// *")
3748
+ (setq comment-end "")
3749
+
3750
+ ;; initialize singular input and output filters. This should be done
3751
+ ;; first as the filters are accessed in the following initialization
3752
+ ;; functions. NOT READY [should be moved to the respective foldings]
3753
+ (make-local-variable 'singular-pre-input-filter-functions)
3754
+ ;;make-local-hook is obsolete in emacs >=21.1
3755
+ ;;(make-local-hook 'singular-post-input-filter-functions)
3756
+ (make-local-variable 'singular-pre-output-filter-functions)
3757
+ ;;(make-local-hook 'singular-post-output-filter-functions)
3758
+
3759
+ (singular-interactive-mode-map-init)
3760
+ (singular-mode-syntax-table-init)
3761
+ (singular-interactive-mode-menu-init)
3762
+ (singular-demo-mode-init)
3763
+ (singular-folding-init)
3764
+ (singular-help-init)
3765
+ (singular-prompt-init)
3766
+ (singular-exec-init)
3767
+
3768
+ ;; Font Lock mode initialization for Emacs. For XEmacs, it is done at
3769
+ ;; singular.el loading time.
3770
+ (cond
3771
+ ;; Emacs
3772
+ ((eq singular-emacs-flavor 'emacs)
3773
+ (singular-interactive-font-lock-init)))
3774
+
3775
+ ;; debugging filter initialization
3776
+ (singular-debug 'interactive-filter
3777
+ (singular-debug-filter-init))
3778
+
3779
+ (run-hooks 'singular-interactive-mode-hook))
3780
+ ;;}}}
3781
+
3782
+ ;;{{{ Starting singular
3783
+ (defcustom singular-same-window t
3784
+ "*Specifies how to open the window for Singular sessions.
3785
+ If this variable equals t, Singular comes up in the selected window.
3786
+ If this variable equals nil, Singular comes up in another window.
3787
+ If this variable equals neither t nor nil, the standard Emacs behaviour to
3788
+ open the window is adopted (which very much depends on the settings of
3789
+ `same-window-buffer-names')."
3790
+ :initialize 'custom-initialize-default
3791
+ :type '(choice (const :tag "This window" t)
3792
+ (const :tag "Other window" nil)
3793
+ (const :tag "Default" default))
3794
+ :group 'singular-interactive-miscellaneous)
3795
+
3796
+ (defcustom singular-start-file "~/.emacs_singularrc"
3797
+ "*Name of start-up file to pass to Singular.
3798
+ If the file named by this variable exists it is given as initial input
3799
+ to any Singular process being started. Note that this may lose due to
3800
+ a timing error if Singular discards input when it starts up."
3801
+ :type 'file
3802
+ :initialize 'custom-initialize-default
3803
+ :group 'singular-interactive-miscellaneous)
3804
+
3805
+ (defcustom singular-executable-default "Singular"
3806
+ "*Default name of Singular executable.
3807
+ Used by `singular' when new Singular processes are started.
3808
+ If the name is given without path the executable is searched using the
3809
+ `PATH' environment variable."
3810
+ :type 'file
3811
+ :initialize 'custom-initialize-default
3812
+ :group 'singular-interactive-miscellaneous)
3813
+
3814
+ (defvar singular-executable-last singular-executable-default
3815
+ "Singular executable name of the last Singular command used.
3816
+
3817
+ This variable is buffer-local.")
3818
+
3819
+ (defcustom singular-directory-default nil
3820
+ "*Default working directory of Singular buffer.
3821
+ Should be either nil (which means do not set the default directory) or an
3822
+ existing directory."
3823
+ :type '(choice (const nil) (directory :value "~/"))
3824
+ :initialize 'custom-initialize-default
3825
+ :group 'singular-interactive-miscellaneous)
3826
+
3827
+ (defvar singular-directory-last singular-directory-default
3828
+ "Working directory of last Singular command used.
3829
+
3830
+ This variable is buffer-local.")
3831
+
3832
+ ;; no singular-directory-history here. Usual file history is used.
3833
+
3834
+ (defcustom singular-switches-default '()
3835
+ "*List of default switches for Singular processes.
3836
+ Should be a list of strings, one string for each switch.
3837
+ Used by `singular' when new Singular processes are started."
3838
+ :type '(repeat string)
3839
+ :initialize 'custom-initialize-default
3840
+ :group 'singular-interactive-miscellaneous)
3841
+
3842
+ (defvar singular-switches-last singular-switches-default
3843
+ "Switches of last Singular command used.
3844
+
3845
+ This variable is buffer-local.")
3846
+
3847
+ (defvar singular-switches-history nil
3848
+ "History list of Singular switches.")
3849
+
3850
+ ; (defvar singular-switches-magic '("-t" "--exec" "if (system(\"version\") > 1304){system(\"--emacs\", 1);};")
3851
+ (defvar singular-switches-magic '("-t" "--emacs")
3852
+ "Additional magic switches for Singular process.
3853
+ List of switch-strings which are automagically added when new Singular
3854
+ processes are started, one string for each command line argument.
3855
+ This list should at least contain the options \"--emacs\" and \"-t\". If
3856
+ you are running a Singular with version < 1.2 , remove option \"--exec\"
3857
+ from the list.")
3858
+
3859
+ (defcustom singular-name-default "singular"
3860
+ "*Default process name for Singular process.
3861
+ Used by `singular' when new Singular processes are started.
3862
+ This string surrounded by \"*\" will also be the buffer name."
3863
+ :type 'string
3864
+ :initialize 'custom-initialize-default
3865
+ :group 'singular-interactive-miscellaneous)
3866
+
3867
+ (defvar singular-name-last singular-name-default
3868
+ "process name of the last Singular command used.
3869
+
3870
+ This variable is buffer-local.")
3871
+
3872
+ (defvar singular-name-history nil
3873
+ "History list of Singular process names.")
3874
+
3875
+ (defun singular-exec-init ()
3876
+ "Initialize defaults for starting Singular.
3877
+
3878
+ This function is called at mode initialization time."
3879
+ (singular-debug 'interactive (message "Initializing exec"))
3880
+ (set (make-local-variable 'singular-executable-last)
3881
+ singular-executable-default)
3882
+ (set (make-local-variable 'singular-directory-last)
3883
+ singular-directory-default)
3884
+ (set (make-local-variable 'singular-name-last)
3885
+ singular-name-default)
3886
+ (set (make-local-variable 'singular-switches-last)
3887
+ singular-switches-default)
3888
+ (set (make-local-variable 'singular-exit-insert-killed-marker)
3889
+ nil)
3890
+ (set (make-local-variable 'singular-exit-cleanup-done)
3891
+ nil))
3892
+
3893
+ (defvar singular-exit-cleanup-done nil
3894
+ "Switch indicating if cleanup after Singular exit is already done.
3895
+ Initial value is nil. Is set to t by `singular-exit-cleanup' and to nil by
3896
+ `singular-exit-sentinel'.
3897
+
3898
+ This variable is buffer-local.")
3899
+
3900
+ (defun singular-exit-cleanup ()
3901
+ "Clean up after termination of Singular.
3902
+ Writes back input ring after regular termination of Singular if process
3903
+ buffer is still alive, deinstalls the library menu und calls several other
3904
+ exit procedures.
3905
+ Assumes that the current buffer is a Singular buffer.
3906
+ Sets the variable `singular-exit-cleanup-done' to t.
3907
+
3908
+ This function is called by `singular-kill-singular' or by
3909
+ `singular-exit-sentinel'."
3910
+ (singular-debug 'interactive
3911
+ (message "exit-cleanup called"))
3912
+ (singular-demo-exit t)
3913
+ (singular-scan-header-exit)
3914
+ (singular-menu-deinstall-libraries)
3915
+ (singular-history-write)
3916
+ (setq singular-exit-cleanup-done t))
3917
+
3918
+ (defun singular-exit-sentinel (process message)
3919
+ "Clean up after termination of Singular.
3920
+ Calls `singular-exit-cleanup' if `singular-exit-cleanup-done' is nil."
3921
+ (save-excursion
3922
+ (singular-debug 'interactive
3923
+ (message "Sentinel: %s" (substring message 0 -1)))
3924
+
3925
+ (if (string-match "finished\\|exited\\|killed" message)
3926
+ (let ((process-buffer (process-buffer process)))
3927
+ (if (and (not singular-exit-cleanup-done)
3928
+ process-buffer
3929
+ (buffer-name process-buffer)
3930
+ (set-buffer process-buffer))
3931
+ (singular-exit-cleanup))))
3932
+ (setq singular-exit-cleanup-done nil)))
3933
+
3934
+ (defun singular-kill-singular ()
3935
+ "Delete the Singular process running in the current buffer.
3936
+ Calls `singular-exit-cleanup' and deletes the Singular process.
3937
+ Inserts a string indicating that the Singular process is killed."
3938
+ (let* ((process (singular-process))
3939
+ (mark (marker-position (process-mark process))))
3940
+ (singular-exit-cleanup)
3941
+ (delete-process process)
3942
+ (save-excursion
3943
+ ;; Because of timing problems it would be better if
3944
+ ;; singular-exit-sentinel would insert this string (see Version 1.41)
3945
+ ;; but this is not possible for XEmacs: The function (process-mark)
3946
+ ;; called within singular-exit-sentinel returns a mark with no
3947
+ ;; associated buffer!
3948
+ (goto-char mark)
3949
+ (insert "// ** Singular process killed **\n"))))
3950
+
3951
+ (defun singular-control-c (mode)
3952
+ "Interrupt the Singular process running in the current buffer.
3953
+ If called interactiveley, asks whether to (a)bort the current Singular
3954
+ command, (q)uit or (r) restart the current Singular process, or (c)ontinue
3955
+ without doing anything (default).
3956
+
3957
+ If called non-interactiveley, MODE should be one of 'abort, 'quit, 'restart,
3958
+ or 'continue."
3959
+ (interactive
3960
+ (let (answer)
3961
+ (while (not answer)
3962
+ (setq answer (read-from-minibuffer
3963
+ "(a)bort current command, (q)uit, (r)estart Singular or (c)ontinue? "))
3964
+ (setq answer
3965
+ (cond ((equal answer "a") 'abort)
3966
+ ((equal answer "c") 'continue)
3967
+ ((equal answer "r") 'restart)
3968
+ ((equal answer "q") 'quit)
3969
+ ((equal answer "") 'continue) ; default: continue
3970
+ (t nil))))
3971
+ (list answer)))
3972
+ (cond
3973
+ ((eq mode 'quit) (singular-kill-singular))
3974
+ ((eq mode 'restart) (singular-restart))
3975
+ ((eq mode 'abort) (interrupt-process (singular-process)))))
3976
+
3977
+ (defun singular-exec (buffer name executable start-file switches)
3978
+ "Start a new Singular process NAME in BUFFER, running EXECUTABLE.
3979
+ EXECUTABLE should be a string denoting an executable program.
3980
+ SWITCHES should be a list of strings that are passed as command line
3981
+ switches. START-FILE should be the name of a file which contents is
3982
+ sent to the process.
3983
+
3984
+ Deletes any old processes running in that buffer.
3985
+ Removes any empty string in SWITCHES before passing to Singular.
3986
+ Moves point to the end of BUFFER.
3987
+ Initializes all important markers and the simple sections.
3988
+ Runs the hooks on `singular-exec-hook'.
3989
+ Returns BUFFER."
3990
+ (let ((old-buffer (current-buffer)))
3991
+ (unwind-protect
3992
+ (progn
3993
+ (set-buffer buffer)
3994
+
3995
+ ;; delete any old processes
3996
+ (let ((process (get-buffer-process buffer)))
3997
+ (if process (delete-process process)))
3998
+
3999
+ ;; create new process
4000
+ (singular-debug 'interactive
4001
+ (message "Starting new Singular: %s %s"
4002
+ executable switches))
4003
+ ;; before passing SWITCHES to Singuar we remove any empty strings
4004
+ ;; because otherwise Singular tries to open a file with an empty
4005
+ ;; file name.
4006
+ (let ((process (comint-exec-1 name buffer
4007
+ executable (delete "" switches))))
4008
+ ;; set process filter and sentinel
4009
+ (set-process-filter process 'singular-output-filter)
4010
+ (set-process-sentinel process 'singular-exit-sentinel)
4011
+ (make-local-variable 'comint-ptyp)
4012
+ (setq comint-ptyp process-connection-type) ; T if pty, NIL if pipe.
4013
+
4014
+ ;; go to the end of the buffer, initialize I/O and simple
4015
+ ;; sections
4016
+ (goto-char (point-max))
4017
+ (singular-input-filter-init (point))
4018
+ (singular-output-filter-init (point))
4019
+ (singular-simple-sec-init (point))
4020
+
4021
+ ;; completion should be initialized before scan header!
4022
+ (singular-completion-init)
4023
+ (singular-scan-header-init)
4024
+ (singular-menu-init)
4025
+
4026
+ ;; feed process with start file and read input ring. Take
4027
+ ;; care about the undo information.
4028
+ (if start-file
4029
+ (let ((buffer-undo-list t) start-string)
4030
+ (singular-debug 'interactive (message "Feeding start file"))
4031
+ (sleep-for 1) ; try to avoid timing errors
4032
+ (insert-file-contents start-file)
4033
+ (setq start-string (buffer-substring (point) (point-max)))
4034
+ (delete-region (point) (point-max))
4035
+ (process-send-string process start-string)))
4036
+
4037
+ ;; read history if present
4038
+ (singular-history-read)
4039
+
4040
+ ;; execute hooks
4041
+ (run-hooks 'singular-exec-hook))
4042
+
4043
+ buffer)
4044
+ ;; this code is unwide-protected
4045
+ (set-buffer old-buffer))))
4046
+
4047
+
4048
+ ;; TODO: Documentation!
4049
+ ;; Note:
4050
+ ;;
4051
+ ;; In contrast to shell.el, `singular' does not run
4052
+ ;; `singular-interactive-mode' every time a new Singular process is
4053
+ ;; started, but only when a new buffer is created. This behaviour seems
4054
+ ;; more intuitive w.r.t. local variables and hooks.
4055
+
4056
+ (defun singular-internal (executable directory switches name)
4057
+ "Run an inferior Singular process, with I/O through an Emacs buffer.
4058
+
4059
+ Appends `singular-switches-magic' to switches.
4060
+ Sets default-directory if directory is not-nil.
4061
+ Sets singular-*-last values."
4062
+ (singular-debug 'interactive
4063
+ (message "singular-internal: %s %s %s %s"
4064
+ executable directory name switches))
4065
+ (let* ((buffer-name (singular-process-name-to-buffer-name name))
4066
+ ;; buffer associated with Singular, nil if there is none
4067
+ (buffer (get-buffer buffer-name)))
4068
+
4069
+ ;; If directory is set, make sure that it ends in a "/" at the end.
4070
+ ;; The check is done on both slash and backslash, but we unconditionally
4071
+ ;; insert a slash. Hopefully that works on NT, too.
4072
+ (and directory
4073
+ (not (memq (aref directory (1- (length directory))) '(?/ ?\\)))
4074
+ (setq directory (concat directory "/")))
4075
+
4076
+ (if (not buffer)
4077
+ (progn
4078
+ ;; create new buffer and call `singular-interactive-mode'
4079
+ (singular-debug 'interactive (message "Creating new buffer"))
4080
+ (setq buffer (get-buffer-create buffer-name))
4081
+ (set-buffer buffer)
4082
+ (and directory
4083
+ (setq default-directory directory))
4084
+
4085
+ (singular-debug 'interactive (message "Calling `singular-interactive-mode'"))
4086
+ (singular-interactive-mode)))
4087
+
4088
+ (if (not (comint-check-proc buffer))
4089
+ ;; create new process if there is none
4090
+ (singular-exec buffer name executable
4091
+ (if (file-exists-p singular-start-file)
4092
+ singular-start-file)
4093
+ (append switches singular-switches-magic)))
4094
+
4095
+ ;; pop to buffer
4096
+ (singular-debug 'interactive (message "Calling `pop-to-buffer'"))
4097
+ (singular-pop-to-buffer singular-same-window buffer))
4098
+
4099
+ ;; Set buffer local singular-*-last-values
4100
+ (setq singular-executable-last executable)
4101
+ (setq singular-directory-last directory)
4102
+ (setq singular-switches-last switches)
4103
+ (setq singular-name-last name)
4104
+ ;; Set global values, too
4105
+ (set-default 'singular-executable-last executable)
4106
+ (set-default 'singular-directory-last directory)
4107
+ (set-default 'singular-switches-last switches)
4108
+ (set-default 'singular-name-last name))
4109
+
4110
+ (defun singular-generate-new-buffer-name (name)
4111
+ "Generate a unique buffer name for a singular interactive buffer.
4112
+ The string NAME is the desired name for the singular interactive
4113
+ buffer, without surrounding stars.
4114
+ The string returned is surrounded by stars.
4115
+
4116
+ If no buffer with name \"*NAME*\" exists, return \"*NAME*\".
4117
+ Otherwise check for buffer called \"*NAME<n>*\" where n is a
4118
+ increasing number and return \"*NAME<n>*\" if no such buffer
4119
+ exists."
4120
+ (let ((new-name (singular-process-name-to-buffer-name name))
4121
+ (count 2))
4122
+ (while (get-buffer new-name)
4123
+ (setq new-name (singular-process-name-to-buffer-name
4124
+ (concat name "<" (format "%d" count) ">")))
4125
+ (setq count (1+ count)))
4126
+ new-name))
4127
+
4128
+ (defun singular ()
4129
+ "Run an inferior Singular process using default arguments.
4130
+ Starts a Singular process, with I/O through an Emacs buffer, using the
4131
+ values of `singular-executable-default', `singular-directory-default',
4132
+ `singular-switches-default', and `singular-name-default'.
4133
+
4134
+ For more information on starting a Singular process and on the arguments
4135
+ see the documentation of `singular-other'. To restart a previously started
4136
+ Singular process use `singular-restart'.
4137
+
4138
+ Every time `singular' starts a new Singular process it runs the hooks
4139
+ on `singular-exec-hook'.
4140
+
4141
+ Type \\[describe-mode] in the Singular buffer for a list of commands."
4142
+ (interactive)
4143
+ (singular-internal singular-executable-default
4144
+ singular-directory-default
4145
+ singular-switches-default
4146
+ singular-name-default))
4147
+
4148
+ (defun singular-restart ()
4149
+ "Run an inferior Singular process using the last arguments used.
4150
+ Starts a Singular process, with I/O through an Emacs buffer, using the
4151
+ previously used arguments.
4152
+ If called within a Singular buffer, uses the arguments of the most recent
4153
+ Singular process started in this buffer. If there is a Singular process
4154
+ running in this buffer, it is deleted without warning!
4155
+ If called outside a Singular buffer, uses the arguments of the most recent
4156
+ Singular process started in any Singular buffer (and does not delete any
4157
+ Singular process).
4158
+ If no last values are available, uses the default values (see documentation
4159
+ of `singular').
4160
+
4161
+ For more information on starting a Singular process and on the arguments
4162
+ see the documentation of `singular-other'.
4163
+
4164
+ Every time `singular-restarts' starts a new Singular process it runs the
4165
+ hooks on `singular-exec-hook'.
4166
+
4167
+ Type \\[describe-mode] in the Singular buffer for a list of commands."
4168
+ (interactive)
4169
+
4170
+ (if (singular-process t)
4171
+ (singular-kill-singular))
4172
+
4173
+ (singular-internal singular-executable-last
4174
+ singular-directory-last
4175
+ singular-switches-last
4176
+ singular-name-last))
4177
+
4178
+ (defun singular-other (executable directory switches name)
4179
+ "Run an inferior Singular process.
4180
+ Starts a Singular process, with I/O through an Emacs buffer.
4181
+
4182
+ If called interactively, the user is asked in the minibuffer area for an
4183
+ existing executable (with or without path), an existing directory or nil
4184
+ (if non-nil, sets the buffers default directory to this directory), the
4185
+ complete command line arguments to be passed to Singular (as a single
4186
+ string) and the buffer name of the singular buffer, which is surrounded by
4187
+ \"*\", if not already. (The process name of the singular process is then
4188
+ given by the buffer name with the surrounding stars stripped.)
4189
+
4190
+ If called non-interactiveley, EXECUTABLE is the name of an existing
4191
+ Singular executable (with or without path), DIRECTORY is the name of an
4192
+ existing directory or nil. If non-nil, sets the buffers default directory
4193
+ to DIRECTORY. SWITCHES is a list of strings where each string contains one
4194
+ command line argument which is passed to Singular, and NAME is the process
4195
+ name of the Singular process (that is, the singular buffer name is given by
4196
+ NAME surrounded by \"*\").
4197
+
4198
+ If buffer exists but Singular is not running, starts new Singular.
4199
+ If buffer exists and Singular is running, just switches to buffer.
4200
+ If a file `~/.emacs_singularrc' exists, it is given as initial input.
4201
+ Note that this may lose due to a timing error if Singular discards
4202
+ input when it starts up.
4203
+
4204
+ If a new buffer is created it is put in Singular interactive mode,
4205
+ giving commands for sending input and handling output of Singular. See
4206
+ `singular-interactive-mode'.
4207
+
4208
+ Every time `singular-other' starts a new Singular process it runs the hooks
4209
+ on `singular-exec-hook'.
4210
+
4211
+ Type \\[describe-mode] in the Singular buffer for a list of commands."
4212
+ (interactive
4213
+ (let* ((exec (read-file-name "Singular executable: "))
4214
+ ;; Remark: Do NOT call `expand-file-name' after the
4215
+ ;; above read-file-name! It has to be possible to enter a command
4216
+ ;; without path which should be searched for in $PATH.
4217
+ ;; `start-process' is intelligent enough to start commands with
4218
+ ;; not-expanded name.
4219
+ (dir (file-name-directory (read-file-name "Default directory: "
4220
+ nil
4221
+ (or singular-directory-default
4222
+ default-directory)
4223
+ t)))
4224
+ (switch "")
4225
+ (bufname (singular-generate-new-buffer-name
4226
+ (downcase (file-name-nondirectory exec)))))
4227
+
4228
+ ;; Get command line arguments and append magic switches
4229
+ ;; TODO: Think about default value: Up to now:
4230
+ ;; Use singular-switches-default as init value for read-from-minibuffer
4231
+ (let ((switches-default singular-switches-default))
4232
+ (while switches-default
4233
+ (setq switch (concat switch (car switches-default) " "))
4234
+ (setq switches-default (cdr switches-default))))
4235
+ ;; note: magic switches are appended by `singular-internal'
4236
+ (setq switch (split-string (read-from-minibuffer "Singular options: "
4237
+ switch nil nil
4238
+ singular-switches-history)
4239
+ " "))
4240
+ ;; Generate new buffer name
4241
+ (let (done)
4242
+ (while (not done)
4243
+ (setq bufname (read-from-minibuffer "Singular buffer name: " bufname))
4244
+ (setq done (or (not (get-buffer bufname))
4245
+ (y-or-n-p "Buffer exists. Switch to that buffer? ")))))
4246
+ (if (string-match "^\\*\\(.*\\)\\*$" bufname)
4247
+ (setq bufname (substring bufname (match-beginning 1) (match-end 1))))
4248
+ (list exec dir switch bufname)))
4249
+
4250
+ (singular-internal executable directory switches name))
4251
+
4252
+ (defun singular-exit-singular (&optional kill-singular-buffer)
4253
+ "Delete Singular process and kill Singular buffer.
4254
+ Deletes the buffers Singular process without warning and writes back the input
4255
+ history to file.
4256
+ If called with prefix argument, kills the Singular buffer."
4257
+ (interactive "P")
4258
+ (singular-debug 'interactive
4259
+ (message "exit singular called"))
4260
+
4261
+ (singular-kill-singular)
4262
+ (if kill-singular-buffer
4263
+ (kill-buffer (current-buffer))))
4264
+ ;;}}}
4265
+ ;;}}}
4266
+
4267
+ (provide 'singular)
4268
+
4269
+ ;;; Local Variables:
4270
+ ;;; fill-column: 75
4271
+ ;;; End:
4272
+
4273
+ ;;; singular.el ends here.