asok / projectile-rails

Emacs Rails mode based on projectile
258 stars 59 forks source link

Function projectile-rails-goto-file-at-point not recognize template format. #160

Open acdesouza opened 2 years ago

acdesouza commented 2 years ago

First of all, I'm a complete emacs noob. So, excuse me if I said something wrong.

I could not open a template using projectile-rails-goto-file-at-point. Am I doing something wrong?

Steps to reproduce

  1. Open emacs using the init file below.
  2. Open a rails project: C-c p p
  3. Select a controller
  4. Move the cursor to the line render :template_name
  5. Use the projectile-rails-goto-file-at-point function.
  6. Behavior 6.1. Expected: Open template for that Controllers Action. 6.2. Current: Opens Dired showing Controllers Views directory and show error: Could not recognize the template's format

https://user-images.githubusercontent.com/97436/154732351-20904a51-4874-47b5-9df1-e4c1ec9c39e8.mov

The init file

Starting emacs on Terminal. Using: emacs --no-init-file -l bugreport.el

;; ~/.emacs.d/bugreport.el

;; Initialize package sources
;; https://github.com/jwiegley/use-package
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))

(unless (package-installed-p 'use-package)
  (package-install 'use-package))

(require 'use-package)
(custom-set-variables '(use-package-always-ensure t))
(custom-set-variables '(use-package-always-defer t))
(custom-set-variables '(use-package-verbose t))

;; Projectile
;; https://github.com/bbatsov/projectile
;; * EDE and CEDET don't work with Ruby
;; * Ag: https://docs.projectile.mx/projectile/usage.html#installing-external-tools
(use-package projectile
  :init
  (projectile-mode +1)
  :bind (:map projectile-mode-map
              ("s-p" . projectile-command-map)
              ("C-c p" . projectile-command-map)))

;; Ruby
(use-package ruby-mode
  :config (setq ruby-deep-arglist nil)) ;; https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Layout/ArgumentAlignment with_fixed_indentation

;; Ruby Electric
;; Autoclose paired syntax elements like parens, quotes, etc
;; https://github.com/ruby/elisp-ruby-electric/tree/f2323cd9b5df3b34aa9810ba8109502824925d23
(use-package ruby-electric
  :after (ruby-mode)
  :config (add-hook 'ruby-mode-hook 'ruby-electric-mode))

;; Rails
;; https://github.com/asok/projectile-rails
(use-package projectile-rails
  :after (projectile)
  :bind
  (:map projectile-rails-mode-map
    ("C-c r" . projectile-rails-command-map))
  ;; Only needed if projectile identifies a project
  :hook
  ((projectile-after-switch-project . projectile-rails-global-mode)))

;; RVM
;; https://github.com/senny/rvm.el
;; Sets the right ruby version and gemset.So, I can C-c r r
;; to open a rails console for the current project
(use-package rvm
  :after (projectile)
  :hook (
  (projectile-after-switch-project . rvm-activate-corresponding-ruby)))

What I could find

I used scratch buffer to rewrite the projectile-rails-goto-file-at-point and add a message to understand what is the format the plugin is finding.

I end up adding all variables because I have no idea how to debug it live.

(message "Current file: `(%s), template: `(%s), dir: `(%s), name: `(%s), format: `(%s)" (projectile-rails-filename-at-point) template dir name format)

Although everything looks right, I found out the function wasn't able to discover/guess the format I'm using.

Current file: ‘(new), template: ‘(new), dir: ‘(/Users/acdesouza/Projects/estudos/demo_rails_7/app/views/posts/), name: ‘(new), format: ‘(html)

Digging a little deeper I believe I found out this is caused by the lack of a default value for the function projectile-rails-template-format.

This line expects the template format being described as: render :new, formats: [:html].

But, Rails could also use:

Sort of... a solution

Adding a match regular expression for the respond_to format worked for me. But, I'm not sure this is the way for a solution.

(at-line-re-respond-to "\\w+\\.\\(\\w+\\)\\s-*\\({\\|do\\)")
[...]
at-line-re-respond-to (projectile-rails-current-line))
           (match-string 1 (projectile-rails-current-line)))
[...]

The whole function

(defun projectile-rails-template-format (template)
  (let ((at-point-re "\\.\\([^.]+\\)\\.[^.]+$")
        (at-line-re "formats?\\(?:'\"\\|:\\)?\\s-*\\(?:=>\\)?\\s-*\\[[:'\"]\\([a-zA-Z0-9]+\\)['\"]?\\]")
        (at-line-re-respond-to "\\w+\\.\\(\\w+\\)\\s-*\\({\\|do\\)"))
    (message "Template: `(%s)" template)
    (cond ((string-match at-point-re template)
           (match-string 1 template))
          ((string-match at-line-re (projectile-rails-current-line))
           (match-string 1 (projectile-rails-current-line)))
          ((string-match at-line-re-respond-to (projectile-rails-current-line))
           (match-string 1 (projectile-rails-current-line)))
          (t
           (when (string-match at-point-re (buffer-file-name))
             (match-string 1 (buffer-file-name)))))))