Skip to content

Instantly share code, notes, and snippets.

@vfsoraki
Last active January 14, 2024 09:20
Show Gist options
  • Save vfsoraki/4f3658defc930b655df125087114ec3b to your computer and use it in GitHub Desktop.
Save vfsoraki/4f3658defc930b655df125087114ec3b to your computer and use it in GitHub Desktop.
ELisp code to switch between controller, view and templates in an Elixir Phoenix project
(setq
vfex--view-regex-old "^lib/\\(.+\\)/views/\\(.+\\)_view.ex"
vfex--template-regex-old "^lib/\\(.+\\)/templates/\\(.+\\)/"
vfex--view-regex-new "^lib/\\(.+\\)/controllers/\\(.+\\)_html.ex"
vfex--template-regex-new "^lib/\\(.+\\)/controllers/\\(.+\\)_html/"
vfex--controller-regex "^lib/\\(.+\\)/controllers/\\(.+\\)_controller.ex"
vfex--liveview-regex "^lib/\\(.+\\)/live/\\(.+\\)_live.ex"
vfex--liveview-template-regex "^lib/\\(.+\\)/live/\\(.+\\)_live.html.heex")
(defun vfex--dot-p (name)
"Predicate to know if a name is dot file or not"
(or (string-equal name ".") (string-equal name "..")))
(defun vfex--view-p (path)
"Predicate to know if a path is view or not"
(or
(string-match vfex--view-regex-new path)
(string-match vfex--view-regex-old path)))
(defun vfex--template-p (path)
"Predicate to know if a path is template or not"
(or
(string-match vfex--template-regex-new path)
(string-match vfex--template-regex-old path)))
(defun vfex--controller-p (path)
"Predicate to know if a path is controller or not"
(string-match vfex--controller-regex path))
(defun vfex--liveview-p (path)
"Predicate to know if a path is liveview or not"
(string-match vfex--liveview-regex path))
(defun vfex--liveview-template-p (path)
"Predicate to know if a path is liveview template or not"
(string-match vfex--liveview-template-regex path))
(defun vfex--switch-to-old-view-from-controller (filename-r)
"Switch to old view of current controller"
(let* ((controller-p (vfex--controller-p filename-r)))
(when (and filename-r controller-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(view_path (concat "lib/" app "/views/" name "_view.ex"))
(view (file-relative-name view_path (file-name-parent-directory filename-r))))
(if (file-exists-p view)
(find-file view)
(message "View %s not found" view))))))
(defun vfex--switch-to-view-from-controller (filename-r)
"Switch to view of current controller"
(let* ((controller-p (vfex--controller-p filename-r)))
(when (and filename-r controller-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(view (concat name "_html.ex")))
(if (file-exists-p view)
(find-file view)
(message "View %s not found" view))))))
(defun vfex--switch-to-old-view-from-template (filename-r)
"Switch to old view of current template"
(let* ((template-p (vfex--template-p filename-r)))
(when (and filename-r template-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(view_path (concat "lib/" app "/views/" name "_view.ex"))
(view (file-relative-name view_path (file-name-parent-directory filename-r))))
(if (file-exists-p view)
(find-file view)
(message "View %s not found" view))))))
(defun vfex--switch-to-view-from-template (filename-r)
"Switch to view of current template"
(let* ((controller-p (vfex--template-p filename-r)))
(when (and filename-r controller-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(view (concat "../" name "_html.ex")))
(if (file-exists-p view)
(find-file view)
(message "View %s not found" view))))))
(defun vfex-switch-to-view ()
"Switch to view from controller or template"
(interactive)
(let* ((root (project-root (project-current)))
(filename (buffer-file-name))
(filename-r (file-relative-name filename root))
(controller-p (vfex--controller-p filename-r))
(template-p (vfex--template-p filename-r)))
(when controller-p
(vfex--switch-to-view-from-controller filename-r)
(vfex--switch-to-old-view-from-controller filename-r))
(when template-p
(vfex--switch-to-view-from-template filename-r)
(vfex--switch-to-old-view-from-template filename-r))))
(defun vfex--switch-to-controller-from-old-view (filename-r)
"Switch to controller of current old view"
(let* ((view-p (vfex--view-p filename-r)))
(when (and filename-r view-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(controller_path (concat "lib/" app "/controllers/" name "_controller.ex"))
(controller (file-relative-name controller_path (file-name-parent-directory filename-r))))
(if (file-exists-p controller)
(find-file controller)
(message "Controller %s not found" controller))))))
(defun vfex--switch-to-controller-from-view (filename-r)
"Switch to controller of current view"
(let* ((view-p (vfex--view-p filename-r)))
(when (and filename-r view-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(controller (concat name "_controller.ex")))
(if (file-exists-p controller)
(find-file controller)
(message "Controller %s not found" controller))))))
(defun vfex--switch-to-controller-from-old-template (filename-r)
"Switch to controller of current old template"
(let* ((template-p (vfex--template-p filename-r)))
(when (and filename-r template-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(controller_path (concat "lib/" app "/controllers/" name "_controller.ex"))
(controller (file-relative-name controller_path (file-name-parent-directory filename-r))))
(if (file-exists-p controller)
(find-file controller)
(message "Controller %s not found" controller))))))
(defun vfex--switch-to-controller-from-template (filename-r)
"Switch to controller of current template"
(let* ((template-p (vfex--template-p filename-r)))
(when (and filename-r template-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(controller (concat "../" name "_controller.ex")))
(if (file-exists-p controller)
(find-file controller)
(message "Controller %s not found" controller))))))
(defun vfex-switch-to-controller ()
"Switch to controller from view or template"
(interactive)
(let* ((root (project-root (project-current)))
(filename (buffer-file-name))
(filename-r (file-relative-name filename root))
(view-p (vfex--view-p filename-r))
(template-p (vfex--template-p filename-r)))
(when view-p
(vfex--switch-to-controller-from-view filename-r)
(vfex--switch-to-controller-from-old-view filename-r))
(when template-p
(vfex--switch-to-controller-from-template filename-r)
(vfex--switch-to-controller-from-old-template filename-r))))
(defun vfex--select-template (path)
"Provide a selection to switch to templates in dir"
(let* ((files (directory-files path))
(templates (cl-remove-if #'vfex--dot-p files))
(template (completing-read "Select an template: " templates)))
(when template (find-file (concat path template)))))
(defun vfex--switch-to-template-from-old-view (filename-r)
"Switch to a template of current old view"
(let* ((view-p (vfex--view-p filename-r)))
(when (and filename-r view-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(path-a (concat "lib/" app "/templates/" name "/"))
(path (file-relative-name path-a (file-name-parent-directory filename-r))))
(if (file-exists-p path)
(vfex--select-template path)
(message "Templates not found in %s" path))))))
(defun vfex--switch-to-template-from-view (filename-r)
"Switch to a template of current view"
(let* ((view-p (vfex--view-p filename-r)))
(when (and filename-r view-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(path (concat name "_html/")))
(if (file-exists-p path)
(vfex--select-template path)
(message "Templates not found in %s" path))))))
(defun vfex--switch-to-old-template-from-controller (filename-r)
"Switch to an old template of current controller"
(let* ((controller-p (vfex--controller-p filename-r)))
(when (and filename-r controller-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(path-a (concat "lib/" app "/templates/" name "/"))
(path (file-relative-name path-a (file-name-parent-directory filename-r))))
(if (file-exists-p path)
(vfex--select-template path)
(message "Templates not found in %s" path))))))
(defun vfex--switch-to-template-from-controller (filename-r)
"Switch to a template of current controller"
(let* ((controller-p (vfex--controller-p filename-r)))
(when (and filename-r controller-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(path (concat name "_html/")))
(if (file-exists-p path)
(vfex--select-template path)
(message "Templates not found in %s" path))))))
(defun vfex-switch-to-template ()
"Switch to a template of view or controller"
(interactive)
(let* ((root (project-root (project-current)))
(filename (buffer-file-name))
(filename-r (file-relative-name filename root))
(controller-p (vfex--controller-p filename-r))
(view-p (vfex--view-p filename-r)))
(when controller-p
(vfex--switch-to-template-from-controller filename-r)
(vfex--switch-to-old-template-from-controller filename-r))
(when view-p
(vfex--switch-to-template-from-view filename-r)
(vfex--switch-to-template-from-old-view filename-r))))
(defun vfex--switch-to-template-from-liveview (filename-r)
"Switch to template of current liveview"
(let* ((liveview-p (vfex--liveview-p filename-r)))
(when (and filename-r liveview-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(template (concat name "_live.html.heex")))
(if (file-exists-p template)
(find-file template)
(message "Template not found in %s" path))))))
(defun vfex--switch-to-liveview-from-template (filename-r)
"Switch to liveview of current template"
(let* ((template-p (vfex--liveview-template-p filename-r)))
(when (and filename-r template-p)
(let* ((app (match-string 1 filename-r))
(name (match-string 2 filename-r))
(liveview (concat name "_live.ex")))
(if (file-exists-p liveview)
(find-file liveview)
(message "LiveView not found in %s" path))))))
(defun vfex-switch-lv-template ()
"Switch between a LiveView and its template"
(interactive)
(let* ((root (project-root (project-current)))
(filename (buffer-file-name))
(filename-r (file-relative-name filename root))
(liveview-p (vfex--liveview-p filename-r))
(template-p (vfex--liveview-template-p filename-r)))
(when liveview-p (vfex--switch-to-template-from-liveview filename-r))
(when template-p (vfex--switch-to-liveview-from-template filename-r))))
(global-set-key (kbd "C-c s c") 'vfex-switch-to-controller)
(global-set-key (kbd "C-c s v") 'vfex-switch-to-view)
(global-set-key (kbd "C-c s t") 'vfex-switch-to-template)
(global-set-key (kbd "C-c s l") 'vfex-switch-lv-template)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment