yowsup.el 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ;;; yowsup-el --- Yowsup for Emacs -*- coding: utf-8; lexical-binding: t -*-
  2. ;;; Copyright © 2018 Alex Vong <alexvong1995@gmail.com>
  3. ;;;
  4. ;;; This file is part of yowsup-el.
  5. ;;;
  6. ;;; yowsup-el is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; yowsup-el is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with yowsup-el. If not, see <http://www.gnu.org/licenses/>.
  18. (require 'cl-lib)
  19. (require 'comint)
  20. (require 'r5rs)
  21. (require 'srfi-1)
  22. (cl-macrolet ((λ (formals form &rest forms)
  23. `(lambda ,formals
  24. ,form
  25. ,@forms))
  26. (add-hook! (hook proc)
  27. `(add-hook ',hook ,proc))
  28. (buffer-exists? (buf-name)
  29. `(get-buffer ,buf-name))
  30. (put! (sym prop val)
  31. `(put ,sym ,prop ,val))
  32. (current-file-name ()
  33. (or byte-compile-current-file ; compile-time
  34. load-file-name ; load-time
  35. buffer-file-name)) ; eval-time
  36. (escape-string (str)
  37. `(replace-regexp-in-string (rx (group (or "'"
  38. "`"
  39. "\\")))
  40. "\\\\=\\1"
  41. ,str))
  42. (escape (x)
  43. (r5-let ((x* (cl-gensym)))
  44. `(r5-let ((,x* ,x))
  45. (if (r5-string? ,x*)
  46. (escape-string ,x*)
  47. ,x*))))
  48. (define-with-docs (var docs val)
  49. `(r5-begin (r5-define ,var ,val)
  50. (put! ',var
  51. 'variable-documentation
  52. (format "Global variable defined in url `%s'.
  53. Default value is `%s'.
  54. %s"
  55. (escape (current-file-name))
  56. (escape (with-output-to-string
  57. (r5-write ,var)))
  58. ,docs)))))
  59. ;; variables intended to be modified by users
  60. (define-with-docs yowsup-process-name
  61. "Default name for Yowsup process."
  62. "Yowsup Cli client")
  63. (define-with-docs yowsup-buffer-name
  64. "Default name for Yowsup buffer."
  65. (r5-string-append "*" yowsup-process-name "*"))
  66. (define-with-docs yowsup-config
  67. "Default configuration file for Yowsup."
  68. "~/.yowsup/config")
  69. (define-with-docs yowsup-init
  70. "Default initialization file for Yowsup."
  71. "~/.yowsup/init")
  72. (define-with-docs yowsup-log
  73. "Default log file for Yowsup."
  74. "~/.yowsup/log")
  75. (define-with-docs yowsup-cli
  76. "Default location for Yowsup Cli."
  77. "~/.local/bin/yowsup-cli")
  78. (define-with-docs yowsup-cli-command
  79. "Default command for Yowsup Cli."
  80. "demos")
  81. (define-with-docs yowsup-cli-args
  82. "Default arguments for Yowsup Cli."
  83. `("--config" ,(expand-file-name yowsup-config)
  84. "--yowsup"))
  85. (define-minor-mode yowsup-logging-mode
  86. "Minor mode for logging Yowsup session."
  87. :lighter " Logging")
  88. (define-derived-mode yowsup-mode comint-mode "Yowsup"
  89. "Major mode for `run-yowsup'."
  90. (yowsup-logging-mode 1))
  91. (define-key yowsup-mode-map (kbd "<tab>") #'completion-at-point)
  92. ;; make current file name referenced in doc string clickable
  93. (let* ((current-file-name-regex (regexp-quote (current-file-name)))
  94. (any-str-regex (rx (* anything)))
  95. (regex-proc-pair? (λ (x)
  96. (pcase-exhaustive x
  97. (`(,(pred r5-string?) . ,_)
  98. t)
  99. (_
  100. '()))))
  101. (regex-proc-alist? (λ (x)
  102. (and (r5-list? x)
  103. (s1-every regex-proc-pair? x)))))
  104. (r5-set! browse-url-browser-function
  105. (cons (cons current-file-name-regex #'browse-url-emacs)
  106. (if (funcall regex-proc-alist? browse-url-browser-function)
  107. browse-url-browser-function
  108. `((,any-str-regex . ,browse-url-browser-function))))))
  109. ;; save to log file when Yowsup buffer is killed if `yowsup-logging-mode' is
  110. ;; enabled
  111. (let* ((end-with-newline? (λ (str)
  112. (string-match-p (rx "\n" eos) str)))
  113. (ensure-final-newline (λ (str)
  114. (if (funcall end-with-newline? str)
  115. str
  116. (r5-string-append str "\n")))))
  117. (add-hook! kill-buffer-hook
  118. (λ ()
  119. (if (and (r5-eq? major-mode 'yowsup-mode)
  120. yowsup-logging-mode)
  121. (r5-let ((content (funcall ensure-final-newline
  122. (buffer-string))))
  123. (append-to-file content '() yowsup-log))
  124. '()))))
  125. ;; completion for Yowsup
  126. (add-hook! comint-dynamic-complete-functions
  127. (λ ()
  128. (if (r5-eq? major-mode 'yowsup-mode)
  129. (r5-let ((match (string-match-p (rx "]:" (* nonl) eos)
  130. (buffer-string))))
  131. (if match
  132. (r5-let ((start (r5+ match (r5-string-length "]:") 1))
  133. (end (point))
  134. (commands '("/L"
  135. "/account"
  136. "/audio"
  137. "/contact"
  138. "/contacts"
  139. "/disconnect"
  140. "/group"
  141. "/groups"
  142. "/help"
  143. "/ib"
  144. "/image"
  145. "/keys"
  146. "/login"
  147. "/message"
  148. "/ping"
  149. "/presence"
  150. "/profile"
  151. "/seq"
  152. "/state"
  153. "/statuses"
  154. "/video")))
  155. (list start end commands))
  156. '()))
  157. '())))
  158. (r5-define (run-yowsup)
  159. "Start Yowsup.
  160. Logging is enabled by default.
  161. To disable it temporarily, toggle `yowsup-logging-mode'.
  162. To disable it permanietly, add the following to your init file:
  163. (add-hook 'yowsup-mode-hook
  164. (lambda ()
  165. (yowsup-logging-mode -1)))"
  166. (interactive)
  167. (if (buffer-exists? yowsup-buffer-name)
  168. (switch-to-buffer yowsup-buffer-name)
  169. (r5-let ((buf (generate-new-buffer yowsup-buffer-name))
  170. (args (cons yowsup-cli-command yowsup-cli-args)))
  171. (switch-to-buffer buf)
  172. (yowsup-mode)
  173. (apply #'make-comint-in-buffer
  174. yowsup-process-name
  175. yowsup-buffer-name
  176. yowsup-cli
  177. yowsup-init
  178. args)))))
  179. (provide 'yowsup)