Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add counsel-url-expand helper for ivy-ffap-url-functions #1164

Closed
wants to merge 12 commits into from

Conversation

bcully
Copy link
Contributor

@bcully bcully commented Aug 15, 2017

counsel-url-expand makes it easy to add keyword to URL expansions for ivy-ffap, simply by adding a (REGEXP . FORMAT) pair to counsel-url-expansions.

counsel-url-expand makes it easy to add keyword to URL expansions for
ivy-ffap, simply by adding a (REGEXP . FORMAT) pair to
counsel-url-expansions.
@bcully
Copy link
Contributor Author

bcully commented Aug 15, 2017

That's what I get for using emacs 25. I'll remove the dependency on seq.

counsel.el Outdated
@@ -1678,6 +1679,57 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer during completion."
(format "http://debbugs.gnu.org/cgi/bugreport.cgi?bug=%s"
(substring url 1)))))))

(defvar counsel-url-expansions
nil
"List of (REGEXP . FORMAT) pairs.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest a summary line slightly more descriptive and suggestive of the variable's purpose, e.g. "Map URL regexps to their expansion format string" or similar. The datatype structure can then be further described in the docstring body.

Another nitpick is that the variable's initial value, nil, could be placed on the same line as the variable's name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

counsel.el Outdated

If the format element is a function, more powerful
transformations are possible. As an example,
'(\"^issue\\([0-9]+\\)$\" .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Why not give regexp examples with beginning and end of string, rather than line, anchors?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E.g.

\"\\`issue\\([[:digit:]]+\\)\\'\"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm less familiar with emacs regular expressions. ^/$ are just more common and the distinction here seems a little academic. But I suppose ` and ' are more precise, so I'll adjust them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hence my starting the comment with 'nitpick'. :) I'm just of the opinion that examples ought to be as precise/idiomatic as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair. As an elisp newbie I appreciate the attention you've given this PR.

counsel.el Outdated
(let ((result (funcall pred elt)))
(when result
(throw 'result result))))
nil))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use cl-some instead of seq-some. FYI, global definitions should be prefixed with the package name by Elisp convention.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, thanks.

(let ((regexp (car pair))
(formatter (cdr pair)))
(when (string-match regexp word-at-point)
(if (functionp formatter)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious - any reason to prefer functionp over fboundp here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a frequent elisp writer, so I don't know the conventions. I preferred functionp because I know that formatter is bound here in the let, and I would tend to use fboundp when I don't know whether a symbol exists at all. But I recognize that we're talking about just the function slot of the symbol (or whatever the word is), so the distinction is hazy. If there's a reason or convention for preferring one over the other I'd be happy to follow it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I should have looked into this more before asking. My habit is simply to ask the author first, because they may have already thought about it.

In older Emacsen, functionp used to return t for any kind of function, including things which can't be passed to funcall, such as macros and special forms. Somehow I also managed to conflate functionp with doing "more than what is usually necessary" in my mind.

Contrast that with the current description of functionp as returning t for any valid argument to funcall. In which case using fboundp instead of functionp here would simply be wrong.

counsel.el Outdated
"Expand word at point using `counsel-url-expansions'.
The first pair in the list whose regexp matches the word at point
will be expanded according to its format. This function is
intended to be used by `ivy-ffap-url-functions' to browse the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I think it reads better to replace "by" with one of "for", "with" or "in", as the object is a variable, not a function, and so does not directly "use" counsel-url-expand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

ivy-test.el Outdated
(ert-deftest counsel-url-expand ()
"Test ffap expansion using counsel-url-expansions."
;; no expansions defined
(let ((counsel-url-expansions nil))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes down to a preference in style, but FYI this can also be written as (let (counsel-url-expansions) ...).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, I'll switch.

ivy-test.el Outdated
"Test ffap expansion using counsel-url-expansions."
;; no expansions defined
(let ((counsel-url-expansions nil))
(should (eql (counsel-url-expand) nil)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Why not just use eq?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah not sure why I used eql, will fix.

ivy-test.el Outdated
(concat "https://foo.com/issues/"
(match-string 1 word)))))))
;; no match
(defun current-word () "foobar")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not a wise idea to permanently redefine this function for the sake of a test. Why not write a convenience function/macro which performs the moral equivalent of

(with-temp-buffer
  (insert "foobar")
  (should (equal (counsel-url-expand) nil)))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't realized that definition would escape the test environment, but indeed it does. Will fix.

counsel.el Outdated

If the format element is a function, more powerful
transformations are possible. As an example,
'(\"\\'issue\\([[:digit:]]+\\)\\'\" .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinko: First anchor should be backtick, not apostrophe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops.

ivy-test.el Outdated
`(with-temp-buffer
(insert ,text)
(goto-char (point-min))
,body))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is more common and general to define body as a &rest argument and then splice it into the backquoted form with ,@body.

Is moving to (point-min) necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll adjust it. The test passes without the goto-char call so I guess it isn't. I'd thought the point would be outside of the word after insert, but apparently not so.

Thanks again for the detailed review.

counsel.el Outdated
@@ -1516,6 +1516,7 @@ TREE is the selected candidate."

(add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p)
(add-to-list 'ivy-ffap-url-functions 'counsel-emacs-url-p)
(add-to-list 'ivy-ffap-url-functions 'counsel-url-expansions)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want to use counsel-url-expand here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, yes. Must have been running stale code locally...

Not the counsel-url-expansions variable that controls it.
@abo-abo abo-abo closed this in 01e305c Sep 11, 2017
abo-abo added a commit that referenced this pull request Sep 11, 2017
* counsel.el: Rename `counsel-url-expansions' to `counsel-url-expansions-alist'.

* ivy-test.el (counsel-url-expand): Flip `ivy--string-buffer' and `equal'. Easier to eval just the `ivy--string-buffer'
  expression and get a string.

Re #1164
@abo-abo
Copy link
Owner

abo-abo commented Sep 11, 2017

Thanks for the contribution.
Sorry for the delays in the review :)
Please review my linked changes on top of your code.
And please consider adding an entry to ivy.org.

@bcully
Copy link
Contributor Author

bcully commented Sep 11, 2017

Thank you for merging. The additional changes look good to me, but I'm an elisp amateur :)
I'll take a look at ivy.org.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants