pest.lisp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. ;; PROMPT_COMMAND='export PS1="$(pest)"'
  2. (defun string-assoc (key alist)
  3. "Shortcut function over :test #'equal for working with TOML alists"
  4. (cdr (assoc key alist :test #'equal)))
  5. (defun find-config ()
  6. (let ((config-paths (list
  7. (concatenate 'string (uiop:getenv "HOME") "/.config/pest/config.toml")
  8. "/etc/pest/config.toml"
  9. (concatenate 'string (uiop:getenv "PWD") "./config"))))
  10. (loop for path-str in config-paths
  11. do (if (probe-file path-str)
  12. (return-from find-config path-str)))))
  13. (defun config-parse (&optional path)
  14. (let ((config-path (if path path (find-config))))
  15. (if config-path
  16. (with-open-file (fh config-path :direction :input)
  17. (let ((file-content (with-output-to-string (out)
  18. (loop for line = (read-line fh nil)
  19. while line
  20. do (format out "~a~%" line)))))
  21. (clop:parse file-content)))
  22. (clop:parse "
  23. [git]
  24. display_head = false
  25. display_branch = false
  26. git_prefix = \"\"
  27. [git.colors]
  28. fg = [0, 120, 50]
  29. bg = [0, 0, 0]
  30. [prompt]
  31. display_user = false
  32. user_suffix = \"\"
  33. display_hostname = false
  34. hostname_suffix = \"\"
  35. display_pwd = true
  36. pwd_suffix = \"\"
  37. prompt_char = \" λ \"
  38. [prompt.colors]
  39. fg = [255, 255, 255]
  40. bg = [0, 0, 0]
  41. "))))
  42. (defvar *config* NIL)
  43. (defun parse-colors (alist)
  44. "Given an alist containing the fg and bg lists, extract and flatten the rgb color ints into chlorophyll rgb-colors
  45. Returns a list with two elements, the fg chlorophyll rgb object and the bg object"
  46. ;; TODO let assignment can be made more compact via lambda for extracting from toml alist eg. with arg "fg" or "bg"
  47. (let ((colors
  48. (list
  49. (string-assoc "fg" (string-assoc "colors" alist))
  50. (string-assoc "bg" (string-assoc "colors" alist)))))
  51. (loop for rgb-list in colors
  52. collect (destructuring-bind (r g b) rgb-list
  53. (chlorophyll:create-rgb-color r g b)))))
  54. ;; Battery
  55. (defvar *display-battery* NIL)
  56. ;; Git
  57. (defvar *display-git* NIL)
  58. (defvar *git-string* NIL)
  59. (defvar *git-style* NIL)
  60. (defun make-style (config key)
  61. "Given a valid TOML config and key, make the chlorophyll style object for the git status string"
  62. (let ((rgb-colors (parse-colors (string-assoc key config))))
  63. (chlorophyll:new-style
  64. :bold T
  65. :foreground (first rgb-colors)
  66. :background (second rgb-colors))))
  67. (defun check-git-enabled (config)
  68. (if (or
  69. (string-assoc "display_head" (string-assoc "git" config))
  70. (string-assoc "display_branch" (string-assoc "git" config)))
  71. T))
  72. (defun check-git-dir ()
  73. (if (probe-file (pathname (concatenate 'string (get-pwd) "/.git")))
  74. T
  75. NIL))
  76. (defun make-git-string (config)
  77. "Emit string that contains git information to be printed. Assumes if called that git info is enabled."
  78. (if (probe-file (pathname (concatenate 'string (get-pwd) "/.git")))
  79. (let ((git-string NIL))
  80. (if (string-assoc "display_head" (string-assoc "git" config))
  81. (setf git-string (concatenate 'string git-string (legit:current-commit "." :short T))))
  82. (if (string-assoc "display_branch" (string-assoc "git" config))
  83. (progn
  84. (if (string-assoc "display_head" (string-assoc "git" config))
  85. (setf git-string (concatenate 'string git-string "|" (legit:current-branch "." :short T)))
  86. (setf git-string (concatenate 'string git-string (legit:current-branch "." :short T)))))) ;; This is messy
  87. (setf git-string (concatenate 'string (string-assoc "git_prefix" (string-assoc "git" config)) git-string))
  88. git-string)))
  89. ;; Prompt
  90. (defvar *prompt-style* NIL)
  91. (defun get-user ()
  92. (uiop:getenv "USER"))
  93. (defun get-hostname ()
  94. (machine-instance))
  95. ;; Regex Scanners
  96. ;; TODO $HOME rendered as /home/user as opposed to ~
  97. (defvar *home-scan* (ppcre:create-scanner (concatenate 'string "^" (format NIL "~a" (user-homedir-pathname)))))
  98. (defun get-pwd ()
  99. (ppcre:regex-replace *home-scan* (uiop:getenv "PWD") "~/"))
  100. (defun make-prompt-string (config)
  101. "Given config options, produce prompt string (eg: user@hostname:dir terminator)"
  102. (let ((prompt-alist (string-assoc "prompt" config))
  103. (prompt-string NIL))
  104. (if (string-assoc "display_user" prompt-alist)
  105. (setf prompt-string (concatenate 'string prompt-string (get-user) (string-assoc "user_suffix" prompt-alist))))
  106. (if (string-assoc "display_hostname" prompt-alist)
  107. (setf prompt-string (concatenate 'string prompt-string (get-hostname) (string-assoc "hostname_suffix" prompt-alist))))
  108. (if (string-assoc "display_pwd" prompt-alist)
  109. (setf prompt-string (concatenate 'string prompt-string (get-pwd) (string-assoc "pwd_suffix" prompt-alist))))
  110. prompt-string))
  111. (defun reload-config ()
  112. (setf *config* (config-parse))
  113. (setf *prompt-style* (make-style *config* "prompt"))
  114. (if (check-git-enabled *config*)
  115. (setf *git-style* (make-style *config* "git"))))
  116. (defun render-prompt ()
  117. "After resolving all config parsing and string generation, render the prompt output here. Produces a stylized string"
  118. (format T "~A" (chlorophyll:stylize *prompt-style* (make-prompt-string *config*)))
  119. (if (and (check-git-enabled *config*) (check-git-dir))
  120. (format T " ~A" (chlorophyll:stylize *git-style* (make-git-string *config*))))
  121. (format T "~A" (string-assoc "prompt_char" (string-assoc "prompt" *config*))))
  122. (defun main ()
  123. (reload-config)
  124. (render-prompt))