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.
230 lines
7.9 KiB
230 lines
7.9 KiB
;;; haskell-session.el --- Haskell sessions -*- lexical-binding: t -*- |
|
|
|
;; Copyright (C) 2011-2012 Chris Done |
|
|
|
;; Author: Chris Done <chrisdone@gmail.com> |
|
|
|
;; This file is not part of GNU Emacs. |
|
|
|
;; This file is free software; you can redistribute it and/or modify |
|
;; it under the terms of the GNU General Public License as published by |
|
;; the Free Software Foundation; either version 3, or (at your option) |
|
;; any later version. |
|
|
|
;; This file is distributed in the hope that it will be useful, |
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
;; GNU General Public License for more details. |
|
|
|
;; You should have received a copy of the GNU General Public License |
|
;; along with GNU Emacs; see the file COPYING. If not, write to |
|
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
;; Boston, MA 02110-1301, USA. |
|
|
|
;;; Commentary: |
|
|
|
;;; Todo: |
|
|
|
;;; Code: |
|
|
|
(require 'cl-lib) |
|
(require 'haskell-cabal) |
|
(require 'haskell-string) |
|
(require 'haskell-customize) |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;; Globals |
|
|
|
;; Used internally |
|
(defvar haskell-session) |
|
|
|
(make-variable-buffer-local 'haskell-session) |
|
|
|
(defvar haskell-sessions (list) |
|
"All Haskell sessions in the Emacs session.") |
|
|
|
(defun haskell-session-tags-filename (session) |
|
"Get the filename for the TAGS file." |
|
(concat (haskell-session-cabal-dir session) "/TAGS")) |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;; Finding/clearing the session |
|
|
|
;;;###autoload |
|
(defun haskell-session-maybe () |
|
"Maybe get the Haskell session, return nil if there isn't one." |
|
(if (default-boundp 'haskell-session) |
|
haskell-session |
|
(setq haskell-session nil))) |
|
|
|
(defun haskell-session-from-buffer () |
|
"Get the session based on the buffer." |
|
(when (and (buffer-file-name) |
|
(consp haskell-sessions)) |
|
(cl-reduce (lambda (acc a) |
|
(let ((dir (haskell-session-get a 'cabal-dir))) |
|
(if dir |
|
(if (string-prefix-p dir |
|
(file-name-directory (buffer-file-name))) |
|
(if acc |
|
(if (and |
|
(> (length (haskell-session-get a 'cabal-dir)) |
|
(length (haskell-session-get acc 'cabal-dir)))) |
|
a |
|
acc) |
|
a) |
|
acc) |
|
acc))) |
|
haskell-sessions |
|
:initial-value nil))) |
|
|
|
(defun haskell-session-default-name () |
|
"Generate a default project name for the new project prompt." |
|
(let ((file (haskell-cabal-find-file))) |
|
(or (when file |
|
(downcase (file-name-sans-extension |
|
(file-name-nondirectory file)))) |
|
"haskell"))) |
|
|
|
(defun haskell-session-assign (session) |
|
"Assing current buffer to SESSION. |
|
More verbose doc string for `haskell-session-assign` |
|
This could be helpfull for temporal or auxilar buffers such as |
|
presentation mode buffers (e.g. in case when session is killed |
|
with all relevant buffers)." |
|
(set (make-local-variable 'haskell-session) session)) |
|
|
|
(defun haskell-session-choose () |
|
"Find a session by choosing from a list of the current sessions." |
|
(when haskell-sessions |
|
(let* ((session-name (funcall haskell-completing-read-function |
|
"Choose Haskell session: " |
|
(cl-remove-if (lambda (name) |
|
(and haskell-session |
|
(string= (haskell-session-name haskell-session) |
|
name))) |
|
(mapcar 'haskell-session-name haskell-sessions)))) |
|
(session (cl-find-if (lambda (session) |
|
(string= (haskell-session-name session) |
|
session-name)) |
|
haskell-sessions))) |
|
session))) |
|
|
|
(defun haskell-session-clear () |
|
"Clear the buffer of any Haskell session choice." |
|
(set (make-local-variable 'haskell-session) nil)) |
|
|
|
(defun haskell-session-lookup (name) |
|
"Get the session by name." |
|
(cl-remove-if-not (lambda (s) |
|
(string= name (haskell-session-name s))) |
|
haskell-sessions)) |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;; Session modules |
|
|
|
(defun haskell-session-strip-dir (session file) |
|
"Strip the load dir from the file path." |
|
(let ((cur-dir (haskell-session-current-dir session))) |
|
(if (> (length file) (length cur-dir)) |
|
(if (string= (substring file 0 (length cur-dir)) |
|
cur-dir) |
|
(replace-regexp-in-string |
|
"^[/\\]" "" |
|
(substring file |
|
(length cur-dir))) |
|
file) |
|
file))) |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
;; Accessing the session |
|
|
|
(defun haskell-session-current-dir (s) |
|
"Get the session current directory." |
|
(let ((dir (haskell-session-get s 'current-dir))) |
|
(or dir |
|
(error "No current directory.")))) |
|
|
|
(defun haskell-session-name (s) |
|
"Get the session name." |
|
(haskell-session-get s 'name)) |
|
|
|
(defun haskell-session-target (s) |
|
"Get the session build target. |
|
If `haskell-process-load-or-reload-prompt' is nil, accept `default'." |
|
(let* ((maybe-target (haskell-session-get s 'target)) |
|
(target (if maybe-target maybe-target |
|
(let ((new-target |
|
(if haskell-process-load-or-reload-prompt |
|
(read-string "build target (empty for default):") |
|
""))) |
|
(haskell-session-set-target s new-target))))) |
|
(if (not (string= target "")) target nil))) |
|
|
|
(defun haskell-session-set-target (s target) |
|
"Set the session build target." |
|
(haskell-session-set s 'target target)) |
|
|
|
(defun haskell-session-set-interactive-buffer (s v) |
|
"Set the session interactive buffer." |
|
(haskell-session-set s 'interactive-buffer v)) |
|
|
|
(defun haskell-session-set-process (s v) |
|
"Set the session process." |
|
(haskell-session-set s 'process v)) |
|
|
|
;;;###autoload |
|
(defun haskell-session-process (s) |
|
"Get the session process." |
|
(haskell-session-get s 'process)) |
|
|
|
(defun haskell-session-set-cabal-dir (s v) |
|
"Set the session cabal-dir." |
|
(let ((true-path (file-truename v))) |
|
(haskell-session-set s 'cabal-dir true-path) |
|
(haskell-session-set-cabal-checksum s true-path))) |
|
|
|
(defun haskell-session-set-current-dir (s v) |
|
"Set the session current directory." |
|
(let ((true-path (file-truename v))) |
|
(haskell-session-set s 'current-dir true-path))) |
|
|
|
(defun haskell-session-set-cabal-checksum (s cabal-dir) |
|
"Set the session checksum of .cabal files" |
|
(haskell-session-set s 'cabal-checksum |
|
(haskell-cabal-compute-checksum cabal-dir))) |
|
|
|
(defun haskell-session-cabal-dir (s) |
|
"Get the session cabal-dir." |
|
(or (haskell-session-get s 'cabal-dir) |
|
(let ((set-dir (haskell-cabal-get-dir (not haskell-process-load-or-reload-prompt)))) |
|
(if set-dir |
|
(progn (haskell-session-set-cabal-dir s set-dir) |
|
set-dir) |
|
(haskell-session-cabal-dir s))))) |
|
|
|
(defun haskell-session-modify (session key update) |
|
"Update the value at KEY in SESSION with UPDATE." |
|
(haskell-session-set |
|
session |
|
key |
|
(funcall update |
|
(haskell-session-get session key)))) |
|
|
|
(defun haskell-session-get (session key) |
|
"Get the SESSION's KEY value. |
|
Returns nil if KEY not set." |
|
(cdr (assq key session))) |
|
|
|
(defun haskell-session-set (session key value) |
|
"Set the SESSION's KEY to VALUE. |
|
Returns newly set VALUE." |
|
(let ((cell (assq key session))) |
|
(if cell |
|
(setcdr cell value) ; modify cell in-place |
|
(setcdr session (cons (cons key value) (cdr session))) ; new cell |
|
value))) |
|
|
|
(provide 'haskell-session) |
|
|
|
;;; haskell-session.el ends here
|
|
|