A JavaScript development environment for Emacs https://indium.readthedocs.io
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

182 lines
6.3 KiB

  1. ;;; indium-render.el --- Helper functions to display JS objects in buffers -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2016-2018 Nicolas Petton
  3. ;; Author: Nicolas Petton <nicolas@petton.fr>
  4. ;; Keywords:
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; Helper functions for inserting content in indium buffers.
  17. ;;; Code:
  18. (require 'seq)
  19. (require 'indium-seq-fix)
  20. (require 'indium-faces)
  21. (require 'indium-structs)
  22. (declare-function indium-debugger-frames-select-frame "indium-debugger.el")
  23. (declare-function indium-inspector-inspect "indium-inspector.el")
  24. (defun indium-render-remote-object (obj)
  25. "Render OBJ, based on its object type.
  26. If OBJ represents a reference to an object, render it with a link
  27. to an inspector on that object."
  28. (cond
  29. ((indium-remote-object-error-p obj)
  30. (indium-render-description obj 'indium-repl-error-face))
  31. ((indium-remote-object-reference-p obj)
  32. (indium-render-object-link obj))
  33. (t
  34. (indium-render-description obj 'indium-repl-stdout-face))))
  35. (defun indium-render-remote-object-to-string (obj)
  36. "Return a string representation of OBJ."
  37. (with-temp-buffer
  38. (indium-render-remote-object obj)
  39. (buffer-string)))
  40. (defun indium-render-description (obj face)
  41. "Insert OBJ fontified with FACE as a description."
  42. (let ((description (indium-remote-object-to-string obj)))
  43. (insert
  44. (propertize description
  45. 'font-lock-face face
  46. 'rear-nonsticky '(font-lock-face)))))
  47. (defun indium-render-keyword (string)
  48. "Insert STRING as fontified as a keyword."
  49. (insert
  50. (propertize string
  51. 'font-lock-face 'indium-keyword-face
  52. 'rear-nonsticky '(font-lock-face))))
  53. (defun indium-render-button (string action)
  54. "Render a button with the label STRING.
  55. When clicked, evaluate ACTION.
  56. ACTION should be a function that takes no argument."
  57. (insert
  58. (propertize string
  59. 'font-lock-face 'indium-button-face
  60. 'indium-action action
  61. 'rear-nonsticky '(font-lock-face indium-action))))
  62. (defun indium-render-header (string)
  63. "Render STRING as a header."
  64. (insert
  65. (propertize string
  66. 'font-lock-face 'indium-header-face
  67. 'rear-nonsticky '(font-lock-face))))
  68. (defun indium-render-object-link (obj)
  69. "Render OBJ as a link, with an optional preview."
  70. (let* ((description (indium-remote-object-to-string obj))
  71. (beg (point))
  72. (end (progn
  73. (insert (indium-render--truncate-string-to-newline description))
  74. (point)))
  75. (face 'indium-link-face))
  76. (set-text-properties beg end
  77. `(font-lock-face ,face
  78. mouse-face highlight
  79. indium-reference ,obj))
  80. (when (indium-remote-object-has-preview-p obj)
  81. (insert (format " %s" (indium-remote-object-preview obj))))))
  82. (defun indium-render-properties (properties)
  83. "Insert all items in PROPERTIES."
  84. (seq-map #'indium-render-property properties))
  85. (defun indium-render-property (property &optional separator)
  86. "Insert the PROPERTY rendered as a remote object.
  87. When SEPARATOR is non-nil, insert it after the property.
  88. Otherwise, insert a newline."
  89. (insert " " (indium-property-name property) ": ")
  90. (indium-render-remote-object (indium-property-remote-object property))
  91. (insert (or separator "\n")))
  92. (defun indium-render-property-to-string (property)
  93. "Return PROPERTY rendered as a string."
  94. (with-temp-buffer
  95. (indium-render-property property "")
  96. (buffer-string)))
  97. (defun indium-render-frame (frame current)
  98. "Render the stack frame FRAME.
  99. If CURRENT is non-nil, FRAME rendered as the current frame. When
  100. clicked, jump in the debugger to the frame."
  101. (let ((file (indium-location-file (indium-frame-location frame))))
  102. (insert (if current "* " " "))
  103. (insert (propertize (indium-render--frame-label frame)
  104. 'font-lock-face (if current
  105. 'indium-highlight-face
  106. 'indium-link-face)
  107. 'rear-nonsticky '(font-lock-face indium-action)
  108. 'indium-action (lambda (&rest _)
  109. (indium-debugger-frames-select-frame frame))))
  110. (when (not (string-empty-p file))
  111. (insert (propertize (format " <%s>" file)
  112. 'font-lock-face 'indium-frame-url-face)))))
  113. (defun indium-render--frame-label (frame)
  114. "Return the label for FRAME to be used in the debugger stack frame list."
  115. (let ((label (indium-frame-function-name frame)))
  116. (if (seq-empty-p label)
  117. "Closure"
  118. label)))
  119. (declare #'indium-inspector-inspect)
  120. (defun indium-follow-link ()
  121. "Follow the link at point."
  122. (interactive)
  123. (let ((reference (get-text-property (point) 'indium-reference))
  124. (action (get-text-property (point) 'indium-action)))
  125. (cond
  126. (reference (indium-inspector-inspect reference))
  127. (action (funcall action)))))
  128. (defun indium-perform-action ()
  129. "Evaluate the button action at point."
  130. (let ((function (get-text-property (point) 'indium-action)))
  131. (funcall function)))
  132. (defun indium-fontify-js (&rest args)
  133. "Fontify ARGS as JavaScript."
  134. (with-temp-buffer
  135. (js-mode)
  136. (apply #'insert args)
  137. (font-lock-fontify-region (point-min) (point-max))
  138. (buffer-string)))
  139. (defun indium-message (&rest args)
  140. "Display ARGS like `message', but fontified as JavaScript."
  141. (message "%s" (apply #'indium-fontify-js args)))
  142. (defun indium-render--truncate-string-to-newline (string)
  143. "Return STRING truncated before the first newline.
  144. If STRING is truncated, append ellipsis."
  145. (let ((result (car (split-string string "\n"))))
  146. (unless (string= string result)
  147. (setq result (concat result "…")))
  148. result))
  149. (provide 'indium-render)
  150. ;;; indium-render.el ends here