;;; 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-customize)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Globals
|
|
|
|
;; Used internally
|
|
(defvar-local haskell-session nil)
|
|
|
|
(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.
|
|
|
|
This could be helpful for temporary or auxiliary buffers such as
|
|
presentation mode buffers (e.g. in case when session is killed
|
|
with all relevant buffers)."
|
|
(setq-local 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."
|
|
(setq-local 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
|