; icicles - file name completion (require 'icicles) (require 'company) (require 'dojo-cdes-jsgen-classes) (require 'dojo-common-log) (require 'dojo-common-source) (require 'dojo-core-api) (require 'dojo-core-files) (require 'dojo-core-load) (require 'dojo-core-save) (require 'dojo-core-workspace) (require 'dojo-js-completion) (require 'dojo-js-extract) (require 'dojo-js-includes) (require 'dojo-js-inspect) (require 'dojo-js-key) (require 'dojo-jsgen-code) (require 'dojo-imports) (defvar dojo-current-workspace (construct-dojo-workspace) "The current workspace" ) (defcustom dojo-workspace-file ".emacs-dojo-workspace.el" "Path (relative to the dojo-current-workspace path) where the serialized version of the current workspace is stored." :type 'string :group 'dojo ) (defcustom dojo-workspace-dir ".emacs-workspace" "Path (relative to the dojo-current-workspace path) where the serialized version of the current workspace is stored as xml files." :type 'string :group 'dojo) (defcustom dojo-activate-log t "If true, dojo-mode will write information to its log buffers. If nil, logging will be completely disabled." :type 'boolean :group 'dojo) (defcustom dojo-log-buffer-limit 250000 "If set, log buffers will be cut to half this size, once this size is exceeded." :type 'integer :group 'dojo) (defcustom dojo-activate-indent-log nil "If true, dojo-mode will write indentation related information to its log buffers. If nil, that kind of logging will be disabled." :type 'boolean :group 'dojo) (defcustom dojo-activate-workspace-log t "If true, dojo-mode will write workspace related information to its log buffers. If nil, that kind of logging will be disabled." :type 'boolean :group 'dojo) (defcustom dojo-workspace-path "/home/wpausch/workspace/" "Workspace path, used e.g. for resolving imports. The path given in this variable must end with a slash." :type 'string :group 'dojo :set (lambda (symbol value) ; Only do this if dojo-minor-mode is actually enabled; otherwise this code ; would aleady be executed on emacs startup, regardless of mode enabled state. (set-default symbol value) (if (and (boundp 'dojo-minor-mode) dojo-minor-mode) (progn (if (boundp 'dojo-workspace-path) (dojo-save-current-workspace)) (dojo-read-current-workspace))))) (defcustom dojo-process-workspace-interval .5 "The interval (measured in seconds) in which the timer for processing/scanning the workspace runs. Each call checks wether work has to be done, does the work if necessary. If the user enters input (i.e. input-ending-p turns to t), the code processing the workspace terminates as quick as possible." :type 'number :group 'dojo ) (defcustom dojo-scan-workspace-interval 86400 "The time (measured since the last workspace scan), after which the workspace scan for interesting projects etc. is performed again." :type 'number :group 'dojo) (defcustom dojo-max-process-workspace-time .1 "Maximum time (measured in seconds) the code processing the workspace (scanning which files exist, parsing them) stays in its loop before it leaves, and waits for its next call. If the user enters input (i.e. input-pending-p turns to t) the loop will be exited regardless of this variable." :type 'number :group 'dojo ) (defcustom dojo-extract-own-class-interval 0.9 "Interval (measured in seconds) to wait between subsequent extractions of the own class, i.e. the class of the currently visited buffer. Code may trigger such extractions based on additional criteria as well, i.e. extraction may in fact happen more often." :type 'number :group 'dojo ) (defcustom dojo-extract-interval 5.0 "Interval (measured in seconds) to wait between subsequent extractions of classes." :type 'number :group 'dojo) (defcustom dojo-extract-imports-interval 86400 "Interval (measured in seconds) to wait between subsequent extractions of imports in a quick, heuristic, manner." :type 'number :group 'dojo) (defcustom dojo-extract-plan-interval 5 "Interval (measured in seconds) between subsequent runs of planning the sequence of future extractions. See (dojo-core-workspace-derive-own-resources-to-parse)." :type 'number :group 'dojo) (defcustom dojo-save-api-interval 600.0 "Interval (measured in seconds) to wait between subsequent saves of the API classes." :type 'number :group 'dojo) (defcustom dojo-save-classes-interval 900.0 "Interval (measured in seconds) to wait between subsequent saves of the classes marked in the dojo-workspace-class-ids-to-save map. I.e., this is the interval in which the results of parsing classes are actually written to the corresponding xml files on disk." :type 'number :group 'dojo) (defcustom dojo-save-dependencies-interval 700.0 "Interval (measured in seconds) to wait between subsequent saves of the dependency xmls." :type 'number :group 'dojo) (defcustom dojo-save-resources-interval 300.0 "Interval (measured in seconds) to wait between subsequent saves of the resources xmls." :type 'number :group 'dojo) (defvar dojo-last-input-timestamp nil "Utcseconds (output of (float-time)) when the last input happened. Currently, determined via post-command-hook, but there might be better ways to do this.") (defcustom dojo-post-input-silence-interval 2.5 "During this interval (measured in seconds) after the last input as stored in dojo-last-input-timestamp, the workspace processing tasks will do nothing, regardless of the other interval settings. The sense of this variable is to keep the GUI responsive. If the user hits a key for input, it's quite probable that another input happens quite soon. So don't even think about delaying the response to such an input by background work." :type 'number :group 'dojo) (defcustom dojo-post-input-estimation-factor 2 "If the running time of an operation can be estimated in advance, only execute it if its estimated running time is smaller than the time since the last input, multiplied by this factor. The idea is that the longer the last input is in the past, the less likely is input in the short future. Thus, if the last input is far away in the past, it's the right moment for long running jobs that can't be interrupted by input. E.g. the extraction of your 5000 lines of code js monster." :type 'number :group 'dojo) (defvar dojo-process-workspace-start-time nil "The UTC seconds where the current run processing the workspace started. Should be set in a way that it only records productive work. E.g., if in a big directory hierarchy, in a corner case more than dojo-max-process-workspace-time is needed to come to the point where one can continue work, this should not lead to an infinite sequence of doing the same tasks again and again.") (defcustom dojo-garbage-collect-interval 5 "Interval (in seconds) for checking wether garbage collection tasks need to be performed. See also dojo-max-loaded-classes." :type 'number :group 'dojo) (defcustom dojo-max-loaded-classes 10 "Number of classes that may be loaded at most. If more are loaded, the oldest ones (with respect to dojo-class-last-needed-utcseconds) are discarded." :type 'integer :group 'dojo) (defcustom dojo-indent-width 4 "Indentation width to use when generating js code" :type 'integer :group 'dojo) (defcustom dojo-webapp-path "/src/main/resources/OSGI-INF/webapp" "Path of the webapp directory relative to a project directory." :type 'string :group 'dojo ) (defcustom dojo-js-extract-max-priority 2 "During resource extraction, only resources with at most this priority (1 is the highest priority, higher values indicate lower priority) are considered. If nil, no priority limit is active. This setting can be used to prevent the extraction code from parsing major parts of the workspace by jumping from import to import in a transitive manner." :type 'integer :group 'dojo) (defcustom dojo-js-enable-automatic-own-class-extraction t "If this variable is t, enable automatic extraction on changes of the own class, i.e. the class of the currently active buffer. Setting this variable to nil might make sense to prevent short delays of editor responsivity. However, in the meantime, dojo-post-input-silence-interval was introduced, which should avoid doing work while the user is typing." :type 'boolean :group 'dojo) (defvar dojo-completion-candidates () "While traversing the AST during completion, here the completion candidates are collected.") (defvar dojo-process-workspace-timer nil "The timer calling dojo-process-workspace, while it is running. Needed to properly call cancel-timer afterwards.") (defvar dojo-last-redisplay-tist nil "Timestamp we called (redisplay) the last time. Used for being able to trigger redisplay in code quite often, but actually execute it more seldom, which is convenient in terms of code organization.") (defcustom dojo-redisplay-interval 0.5 "Minimum interval (measured in seconds), in which we want to trigger redisplay explicitely by calling (redisplay)." :type 'number :group 'dojo) (defcustom dojo-catch-extract-errors t "Wether to automatically catch errors during extraction. Ensures that workspace extractions proceed even if for certain files, errors occur during parsing; but on the other hand, this makes debugging somewhat more difficult." :type 'boolean :group 'dojo) (defcustom dojo-enable-memory-log nil "Activates output of memory information in *Workspace Inspection Log*. That information is derived by running (garbage-collect), which is a quite CPU intensive task. In tests, enabling this option raised CPU usage from 3 to 5 percent to around 30 percent. The sense of that output is getting some picture wether the code analysis we do causes memory problems, or wether things work ok with respect to that." :type 'boolean :group 'dojo) (defvar dojo-test-ast nil "For testing, keep the same AST, instead of continuosuly producing new ones.") (defcustom dojo-css-default-css-file '() "This alist maps project names to paths of the default css file." :type 'alist :group 'dojo) (defun split-and-show-messages () (interactive) (delete-other-windows) (split-window-below) (other-window 1) ; (switch-to-buffer "*Log*") ; (switch-to-buffer "*Load Log*") ; (switch-to-buffer "*Extract Assignments Log*") (switch-to-buffer "*Java Log*") ; (switch-to-buffer "*Data Log*") ; (switch-to-buffer "*Workspace Inspection Log*") ; (switch-to-buffer "*Workspace Detail Log*") ; (switch-to-buffer "*Extract Js Log*") ; (switch-to-buffer "*Completion Generation Log*") ; (switch-to-buffer "*Js API Log*") ; (switch-to-buffer "*Key Log*") ; (switch-to-buffer "*Save Log*") ; (switch-to-buffer "*Inspect Log*") ; (switch-to-buffer "*Indendation Log*") ; (switch-to-buffer "*I18n Log*") ; (switch-to-buffer "*CSS Log*") ; (switch-to-buffer "*Blueprint Completion Log*") ; (switch-to-buffer "*Blueprint Parse Log*") (other-window 1) ) (defun split-and-show-messages-buffer () (interactive) (delete-other-windows) (split-window-below) (other-window 1) (switch-to-buffer (messages-buffer)) (other-window 1)) (defun dojo-toggle-activate-log () (interactive) (setq dojo-activate-log (not dojo-activate-log)) (if dojo-activate-log (message "Activated logging to buffers like *Log*") (message "Disabled logging, dojo-mode will now run pretty quietly.") ) ) (defun dojo-toggle-active-own-class-extraction () (interactive) (setq dojo-js-enable-automatic-own-class-extraction (not dojo-js-enable-automatic-own-class-extraction)) (if dojo-js-enable-automatic-own-class-extraction (message "Activated automatic extraction of active buffer class on changes.") (message "Disabled automatic extraction of active buffer class on changes."))) (defun dojo-print-point () (interactive) (message "Point is [%s]" (point)) ) (defvar dojo-minor-mode-map (let ((map (make-keymap)) ) ; (define-key map "." 'dojo-ac-dot-complete) ; (define-key map (kbd "C-i") 'dojo-js-indent-indent-current-buffer) (define-key map "\C-xf" 'dojo-locate-workspace) (define-key map "\C-xi" 'dojo-include-file) (define-key map "\C-c\C-b" 'blueprint-parse-parse-current-services-xml) (define-key map "\C-c\C-f" 'dojo-add-function) ; (define-key map "\C-c\C-o" 'dojo-print-point) (define-key map "\C-c\C-p" 'dojo-run-parser) (define-key map "\C-c\C-v" 'dojo-extract-and-print-class) ; (define-key map "\C-c\C-k" 'dojo-process-workspace) ; (define-key map "\C-c\C-i" 'dojo-js-extract-extract-own-class) (define-key map "\C-c\C-i" 'dojo-core-workspace-extract-current-file) (define-key map "\C-c\C-k" 'dojo-js-extract-extract-own-class-with-dependencies) (define-key map "\C-c\C-c\C-f" 'dojo-common-log-log-memory-info) ; Keys prefixed by C-c C-j call functions for generating pieces of js code (define-key map "\C-c\C-j\C-a" 'dojo-jsgen-code-insert-then-block) (define-key map "\C-c\C-j\C-c" 'dojo-js-tree-show-css) (define-key map "\C-c\C-j\C-d" 'dojo-jsgen-code-insert-construct-div) ; (define-key map "\C-c\C-j\C-l" 'dojo-cdes-jsgen-generate-list-widget-with-actions) (define-key map "\C-c\C-j\C-h" 'dojo-js-navigation-jump-to-tree-pos) (define-key map "\C-c\C-j\C-p" 'dojo-cdes-jsgen-generate-page) (define-key map "\C-c\C-j\C-o" 'dojo-core-workspace-extract-own-class) (define-key map "\C-c\C-j\C-t" 'dojo-cdes-jsgen-generate-title-pane-widget) (define-key map (kbd "C-c C-g C-i") 'dojo-cdes-jsgen-generate-instance-class) (define-key map (kbd "C-c C-g C-s") 'dojo-cdes-jsgen-generate-static-class) (define-key map "\C-c\C-p" 'dojo-print-point) (define-key map "\C-c\C-q" 'dojo-toggle-activate-log) (define-key map "\C-c\C-o\C-c" 'dojo-core-util-write-class-to-log) ; (define-key map "\C-c\C-o\C-i" 'dojo-js-inspect-print-inspect-path-at-point) (define-key map "\C-c\C-o\C-k" 'dojo-js-key-print-node-key-at-point) (define-key map "\C-c\C-u\C-c" 'dojo-uwsgi-start-cdes) (define-key map "\C-c\C-u\C-e" 'dojo-uwsgi-start-esm) (define-key map "\C-c\C-u\C-m" 'dojo-uwsgi-start-mda) (define-key map "\C-c\C-u\C-n" 'dojo-uwsgi-stop) (define-key map "\C-c\C-u\C-p" 'dojo-core-workspace-remove-parse-failed) (define-key map "\C-c\C-u\C-o" 'dojo-uwsgi-start-obusec) (define-key map "\C-c\C-u\C-r" 'dojo-uwsgi-start-rsecm) (define-key map "\C-c\C-u\C-t" 'dojo-uwsgi-start-tisgraph) (define-key map "\C-c\C-u\C-w" 'dojo-core-workspace-toggle-timer) (define-key map "\C-c\C-u\C-u" 'dojo-js-extract-loop-extract-as) (define-key map "\C-c\C-w\C-s" 'dojo-core-workspace-scan-current-workspace-interactively) (define-key map (kbd "\C-x C-j") 'dojo-core-window-show-symbols-buffer) (define-key map (kbd "\C-x C-ö") 'dojo-core-window-delete-side-windows) ; (define-key map (kbd "C-x C-j C-s") 'dojo-core-workspace-trigger-workspace-scan) ; (define-key map (kbd "C-x C-j C-i") 'dojo-core-workspace-trigger-derive-imports) ; (define-key map (kbd "C-x C-j C-p") 'dojo-core-workspace-trigger-plan-extractions) ; (define-key map (kbd "C-x C-j C-e") 'dojo-core-workspace-trigger-extractions) ; (define-key map (kbd "C-x C-j C-v") 'dojo-core-workspace-trigger-save) (define-key map (kbd "\C-x C-l C-ä") 'dojo-core-window-show-log-buffer) (define-key map (kbd "\C-x C-l C-p") 'dojo-core-window-show-api-log) (define-key map (kbd "\C-x C-l C-a") 'dojo-core-window-show-assignments-log) (define-key map (kbd "\C-x C-l C-b C-c") 'dojo-core-window-show-blueprint-completion-log) (define-key map (kbd "\C-x C-l C-b C-p") 'dojo-core-window-show-blueprint-parse-log) (define-key map (kbd "\C-x C-l C-c") 'dojo-core-window-show-completion-log) (define-key map (kbd "\C-x C-l C-y") 'dojo-core-window-show-data-log) (define-key map (kbd "\C-x C-l C-d") 'dojo-core-window-show-dependency-log) (define-key map (kbd "\C-x C-l C-e") 'dojo-core-window-show-extract-log) (define-key map (kbd "\C-x C-l C-r") 'dojo-core-window-show-extract-prio-log) (define-key map (kbd "\C-x C-l C-8") 'dojo-core-window-show-i18n-log) (define-key map (kbd "\C-x C-l C-o") 'dojo-core-window-show-indentation-log) (define-key map (kbd "\C-x C-l C-i") 'dojo-core-window-show-inspect-log) (define-key map (kbd "\C-x C-l C-j") 'dojo-core-window-show-java-log) (define-key map (kbd "\C-x C-l C-k") 'dojo-core-window-show-key-log) (define-key map (kbd "\C-x C-l C-l") 'dojo-core-window-show-load-log) (define-key map (kbd "\C-x C-l C-s") 'dojo-core-window-show-css-log) (define-key map (kbd "\C-x C-l C-t") 'dojo-core-window-show-tree-log) (define-key map (kbd "\C-x C-l C-u") 'dojo-core-window-show-user-log) (define-key map (kbd "\C-x C-l C-v") 'dojo-core-window-show-save-log) (define-key map (kbd "\C-x C-l C-w") 'dojo-core-window-show-workspace-log) (define-key map (kbd "\C-x C-l C-x") 'dojo-core-window-show-workspace-details-log) (define-key map (kbd "\C-x C-l C-y") 'dojo-core-window-show-workloop-log) (define-key map (kbd "\C-x C-l C-r") 'dojo-js-extract-print-import-resources) (define-key map (kbd "\C-x SPC") 'back-button-global-backward) (define-key map (kbd "\C-x C-n") 'back-button-global-forward) map ) "Keymap for dojo-minor-mode" ) ;(add-to-list 'auto-mode-alist '("\\.js\\'" . dojo-mode)) ;;;###autoload (define-minor-mode dojo-minor-mode "Minor mode with additions to js2-mode, based on icicle, to support developing our Dojo code" :global t :lighter " Dojo-Minor" :keymap dojo-minor-mode-map (or global-mode-string (setq global-mode-string '(""))) (if dojo-minor-mode (progn (message "Enabling dojo-minor-mode") ; Initialize things like most-positive-float (cl-float-limits) ; (add-hook 'js-mode-hook (lambda () (local-unset-key (kbd "C-c C-j")))) (if (null dojo-core-window-js-mode-line-string) (setq dojo-core-window-js-mode-line-string "")) (add-to-list 'global-mode-string 'dojo-core-window-js-mode-line-string t) (dojo-read-current-workspace) (setq tab-width dojo-indent-width) (setq indent-tabs-mode nil) (setq company-minimum-prefix-length 1) (setq debug-on-error t) (if (and (buffer-file-name) (string/ends-with (buffer-file-name) "services\\.xml")) (blueprint-parse-if-necessary)) ; TODO Outcomment to make class parsing purely manually ; (setq dojo-process-workspace-timer (run-at-time dojo-process-workspace-interval dojo-process-workspace-interval 'dojo-process-workspace)) ; (run-at-time dojo-process-workspace-interval nil 'dojo-process-workspace) ; (run-with-idle-timer 2 t 'dojo-collect-classes) (dojo-uwsgi-set-project dojo-uwsgi-project) (dojo-core-window-initialize-side-windows) (let* ((symbols-buffer (get-buffer-create "*Symbols*"))) (display-buffer symbols-buffer)) ) (progn (message "Disabling dojo-mode") (setq global-mode-string (delq 'dojo-core-window-js-mode-line-string global-mode-string)) (if (not (null dojo-process-workspace-timer)) (cancel-timer dojo-process-workspace-timer)) (setq dojo-process-workspace-timer nil) (dojo-save-current-workspace) ) ) ) ;(add-hook 'js2-mode-hook 'dojo-mode) (add-hook 'dojo-mode-hook 'column-number-mode) (add-hook 'kill-emacs-hook (lambda () (condition-case nil (if dojo-minor-mode (dojo-save-current-workspace) nil) (message "Error while saving the workspace, it may remain in an corrupted state.")))) (defun dojo-record-input-timestamp () (setq dojo-last-input-timestamp (float-time))) (add-hook 'post-command-hook 'dojo-record-input-timestamp) (add-hook 'buffer-list-update-hook 'dojo-core-workspace-trigger-plan-extractions) (provide 'dojo-minor-mode)