diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | snakemake.el | 86 |
2 files changed, 91 insertions, 0 deletions
@@ -13,6 +13,11 @@ NEWS -- history of user-visible changes -*- mode: org; -*- - The 'wrapper' keyword is now recognized. +- New command ~snakemake-graph~ displays the graph of dependencies for + a rule. (Thanks to Endre Bakken Stovner for the idea and initial + implementation.) + + * v0.3.0 ** New features diff --git a/snakemake.el b/snakemake.el index 20ec2cd..e72388b 100644 --- a/snakemake.el +++ b/snakemake.el @@ -128,6 +128,20 @@ Used by `snakemake-region-file-targets'." :type 'regexp :package-version '(snakemake-mode . "0.4.0")) +(defcustom snakemake-dot-program "dot" + "Program used to save the graph with `snakemake-graph-save'. +This program must have an option '-T' that can be used to specify +the output type. See 'man dot'." + :type 'string + :package-version '(snakemake-mode . "0.4.0")) + +(defcustom snakemake-graph-default-extension ".svg" + "Extension used by `snakemake-graph-save'. +This should be a valid value for the '-T' option of +`snakemake-dot-program'." + :type 'string + :package-version '(snakemake-mode . "0.4.0")) + ;;; Utilities @@ -351,6 +365,78 @@ targets." " ")) +;;; Graphing commands + +(defvar-local snakemake-graph-rule nil) + +;;;###autoload +(defun snakemake-graph (rules &optional rule-graph) + "Display graph for DAG of RULES. + +The graph will be processed by `snakemake-dot-program' and +displayed with `image-mode'. From this buffer, you can call +\\<snakemake-graph-mode-map>\\[snakemake-graph-save] to save the graph. + +If prefix argument RULE-GRAPH is non-nil, pass --rulegraph +instead of --dag to snakemake. + +$ snakemake --{dag,rulegraph} -- RULES | display" + (interactive (list (or (snakemake-file-targets-at-point 'check) + (snakemake-rule-at-point 'target) + (snakemake-read-rule 'targets)) + current-prefix-arg)) + (unless (listp rules) + (setq rules (list rules))) + (let ((dir (snakemake-snakefile-directory))) + (with-current-buffer (get-buffer-create "*Snakemake graph*") + (setq default-directory dir) + (let ((inhibit-read-only t)) + (erase-buffer) + (apply #'call-process snakemake-program nil t nil + (if rule-graph "--rulegraph" "--dag") + rules)) + (image-mode) + (snakemake-graph-mode) + (setq snakemake-graph-rule (mapconcat #'file-name-nondirectory rules "-")) + (pop-to-buffer (current-buffer))))) + +(defun snakemake-graph-save () + "Save graph in current buffer to file. +The default extension of the file is +`snakemake-graph-default-extension', but you can enter any +extension that the dot program supports." + (interactive) + (unless snakemake-graph-rule + (user-error "Not in Snakemake graph buffer")) + (let ((file (read-file-name "To file: " nil nil nil + (concat snakemake-graph-rule + snakemake-graph-default-extension)))) + (unless (or (string-match-p "\\`\\s-*\\'" file) + (and (file-exists-p file) + (not (y-or-n-p + (concat file " already exists. Overwrite?"))))) + (call-process-region (point-min) (point-max) + snakemake-dot-program nil (list :file file) nil + "-T" (file-name-extension file))))) + +(defvar snakemake-graph-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-s") #'snakemake-graph-save) + map) + "Keymap for Snakemake-graph mode.") + +(define-minor-mode snakemake-graph-mode + "Toggle Snakemake-graph mode. + +With a prefix argument ARG, enable Snakemake-graph mode if ARG is +positive, and disable it otherwise. If called from Lisp, enable +the mode if ARG is omitted or nil. + +Snakemake-graph mode is a minor mode that provides a key, +\\<snakemake-graph-mode-map>\\[snakemake-graph-save], for saving the graph to an output file." + :keymap snakemake-graph-mode-map) + + ;;; Compilation commands (add-to-list 'compilation-error-regexp-alist 'snakemake) |