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

Function to toggle gfm checkbox #7

Closed
hmelman opened this issue Jul 27, 2015 · 7 comments
Closed

Function to toggle gfm checkbox #7

hmelman opened this issue Jul 27, 2015 · 7 comments

Comments

@hmelman
Copy link
Contributor

hmelman commented Jul 27, 2015

I find the following function useful to toggle gfm style checkboxes with the mouse. Perhaps it's useful to include in markdown-mode. Maybe it would be better implemented using make-button.

(defun hrm-markdown-toggle-gfm-check-box (event)
"Click in a gfm task list and toggle its state."
(interactive "*e")
;; go to where the event occurred
(set-buffer (window-buffer (posn-window (event-start event))))
(goto-char (posn-point (event-start event)))

;; assume on a list line (so false positive if [ ] in middle of text)
;; point could be at either position inside the checkbox
;; " [| ] " or " [ |] " or " [|X] " or " [X|] "
(save-match-data
(save-excursion
(forward-char -2)
(let* ((box-regexp " [([ xX])] ")
(at-box (looking-at box-regexp)))
(unless at-box
(forward-char -1)
(setq at-box (looking-at box-regexp)))
(if at-box
(replace-match (if (string= " " (match-string 1)) "x" " ")
nil nil nil 1))))))

@jrblevin
Copy link
Owner

Thanks--I will try to work this in soon. Would, say, <M-mouse-1> (hold meta and click first mouse button) be an appropriate keybinding for this?

Edit: I realize now that <M-mouse-1> would interfere with secondary selection (which I don't use). So, I'm open to other suggestions on the binding.

@hmelman
Copy link
Contributor Author

hmelman commented Jul 28, 2015

On Jul 28, 2015, at 4:02 PM, Jason Blevins notifications@github.com wrote:

Thanks--I will try to work this in soon. Would, say, (hold meta and click first mouse button) be an appropriate keybinding for this?

Great.

M-mouse-1 would work. I’ve been using M-mouse-2.

All the M-mouse keys default to secondary-selection functions that I think no one uses, so I think it’s fine to use any of them.

As I said, an implementation using make-button might be nice. You’d get a mouse-over face for free. It would involve scanning the buffer at startup and an after-change hook but it’s not too hard. If you’d like some code for that I could take a shot.

Howard

@jrblevin
Copy link
Owner

jrblevin commented Aug 7, 2015

Thanks again, Howard. Sorry for the delay in responding. GFM features are lower priority for me than some other things right now, like fixing known bugs and improving the core Markdown functionality, but if you want to take a shot at a patch for implementing this with make-button I'd be happy to take a look.

@hmelman
Copy link
Contributor Author

hmelman commented Aug 8, 2015

On Aug 7, 2015, at 3:37 PM, Jason Blevins notifications@github.com wrote:

Thanks again, Howard. Sorry for the delay in responding. GFM features are lower priority for me than some other things right now, like fixing known bugs and improving the core Markdown functionality, but if you want to take a shot at a patch for implementing this with make-button I'd be happy to take a look.

Thanks again, and I agree with your prioritization.

Ok, I have something working. Like other buttons It toggles with both mouse-1 and RET when in a checkbox and is enabled on a defcustom for markdown-make-gfm-checkboxes-buttons.

Currently it’s tied into gfm-mode. If you approve I’d rather it be in the standard markdown-mode. I’d still keep the markdown-make-gfm-checkboxes-buttons option, but I’d change some names to make it fit in better.

Marked 2 has a preference to render checkboxes that’s separate from other GFM options. As a result I use these in many small notes that are lists of things (movies to see, restaurants to try, etc.) where I don’t care about the other GFM features.

Let me know what you’d prefer.

Howard

@hmelman
Copy link
Contributor Author

hmelman commented Aug 9, 2015

Here’s a patch that applies it to markdown-mode. Let me know what you think.

*** /Users/hmelman/.emacs.d/elpa/markdown-mode-20150807.424/markdown-mode.el Sat Aug 8 14:43:25 2015
--- /Users/hmelman/elisp/markdown-mode.el Sun Aug 9 16:14:54 2015


*** 572,577 ****
--- 572,582 ----
;; this variable buffer-local allows `markdown-mode' to override
;; the default behavior induced when the global variable is non-nil.
;;

  • ;; * `markdown-make-gfm-checkboxes-buttons' - Whether GitHub Flavored
  • ;; Markdown style checkboxes should be turned into buttons that can
  • ;; be toggled with mouse-1 or RET. If non-nil buttons are enabled, the
  • ;; default is t. This works in markdown-mode' as well asgfm-mode'.
  • ;;
    ;; Additionally, the faces used for syntax highlighting can be modified to
    ;; your liking by issuing M-x customize-group RET markdown-faces
    ;; or by using the "Markdown Faces" link at the bottom of the mode
    *** 733,738 ****
    --- 738,744 ----
    ;; * Matt McClure matthewlmcclure@gmail.com for a patch to prevent
    ;; overwriting source files with .html extensions upon export.
    ;; * Roger Bolsius roger.bolsius@gmail.com for ordered list improvements.
  • ;; * Howard Melman hmelman@gmail.com for supporting gfm checkboxes as buttons.
    ;; * Google's Open Source Programs Office for recognizing the project with
    ;; a monetary contribution in June 2015.

*** 966,971 ****
--- 972,982 ----
(const :tag "lazy lock" lazy-lock-mode)
(const :tag "jit lock" jit-lock-mode)))

  • (defcustom markdown-make-gfm-checkboxes-buttons t
  • "When non-nil, make GFM checkboxes into buttons."
  • :group 'markdown
  • :type 'boolean)

  • ;;; Font Lock =================================================================

*** 1055,1060 ****
--- 1066,1077 ----
(defvar markdown-metadata-value-face 'markdown-metadata-value-face
"Face name to use for metadata values.")

  • (defvar markdown-gfm-checkbox-face 'markdown-gfm-checkbox-face

  • "Face name to use for GFM checkboxes.")

  • (defvar markdown-highlight-face 'markdown-highlight-face

  • "Face name to use for mouse highlighting.")

  • (defgroup markdown-faces nil
    "Faces used in Markdown Mode"
    :group 'markdown


    *** 1200,1205 ****
    --- 1217,1232 ----
    "Face for metadata values."
    :group 'markdown-faces)

  • (defface markdown-gfm-checkbox-face

  • '((t (:inherit font-lock-keyword-face)))

  • "Face for GFM checkboxes."

  • :group 'markdown-faces)

  • (defface markdown-highlight-face

  • '((t (:inherit highlight)))

  • "Face for mouse highlighting."

  • :group 'markdown-faces)
    q+
    (defconst markdown-regex-link-inline
    "(!)?([([^]^][^]]|)])((([^)]?)(?:\s-+("[^\"]*"))?))"
    "Regular expression for a text or an image link text.


*** 1369,1374 ****
--- 1396,1406 ----
"|" markdown-regex-angle-uri ")")
"Regular expression for matching any recognized link.")

  • (defconst markdown-regex-gfm-checkbox

  • " ([[ xX]]) "

  • "Regular expression for matching GFM checkboxes.

  • Group 1 matches the text to become a button.")

  • (defconst markdown-regex-block-separator
    "(`|(\n[ \t]*\n)[^\n \t])"
    "Regular expression for matching block boundaries.")


    *** 4843,4848 ****
    --- 4875,4921 ----
    (markdown-reload-extensions)))

  • ;;; GFM Checkboxes as Buttons =================================================

  • (require 'button)

  • (define-button-type 'markdown-gfm-checkbox-button

  • 'follow-link t

  • 'face 'markdown-gfm-checkbox-face

  • 'mouse-face 'markdown-highlight-face

  • 'action #'markdown-toggle-gfm-checkbox)

  • (defun markdown-toggle-gfm-checkbox (button)

  • "Toggle a GFM checkbox clicked on."

  • (save-match-data

  • (save-excursion
    
  •   (goto-char (button-start button))
    
  •   (cond ((looking-at "\[ \]")
    
  •          (replace-match "[x]" nil t))
    
  •         ((looking-at "\[[xX]\]")
    
  •          (replace-match "[ ]" nil t))))))
    
  • (defun markdown-make-gfm-checkboxes-buttons (start end)

  • "Make GFM checkboxes buttons in region between START and END."

  • (save-excursion

  • (goto-char start)
    
  • (let ((case-fold-search t))
    
  •   (save-excursion
    
  • (while (re-search-forward markdown-regex-gfm-checkbox end t)

  • (make-button (match-beginning 1) (match-end 1) 
    
  •                    :type 'markdown-gfm-checkbox-button))))))
    
  • ;; Called when any modification is made to buffer text.

  • (defun markdown-gfm-checkbox-after-change-function (beg end old-len)

  • "Add to `after-change-functions' to setup GFM checkboxes as buttons."

  • (save-excursion

  • (save-match-data
    
  •   ;; Rescan between start of line from `beg' and start of line after`end'.
    
  •   (markdown-make-gfm-checkboxes-buttons
    
  •    (progn (goto-char beg) (beginning-of-line) (point))
    
  •    (progn (goto-char end) (forward-line 1) (point))))))
    

  • ;;; Mode Definition ==========================================================

    (defun markdown-show-version ()


    *** 4954,4959 ****
    --- 5027,5037 ----
    ;; Anytime text changes make sure it gets fontified correctly
    (add-hook 'after-change-functions 'markdown-check-change-for-wiki-link t t)

  • ;; Make checkboxes buttons

  • (when markdown-make-gfm-checkboxes-buttons

  • (markdown-make-gfm-checkboxes-buttons (point-min) (point-max))
    
  • (add-hook 'after-change-functions 'markdown-gfm-checkbox-after-change-function t t))
    
  • ;; If we left the buffer there is a really good chance we were
    ;; creating one of the wiki link documents. Make sure we get
    ;; refontified when we come back.

@jrblevin
Copy link
Owner

Thanks for this patch. I just got around to applying and testing it and it looks fine to me. I did make one small change: I used the same face for checkboxes as was used for list markers. Also, I think it's fine to enable this in markdown-mode. Here is the commit: 4121324.

One more thing: if you could write a test case or two to add to tests/markdown-test.el, that would be very helpful. I will close this issue now, so please just start a new pull request if you want to add some tests.

@hmelman
Copy link
Contributor Author

hmelman commented Aug 14, 2015

On Aug 13, 2015, at 12:44 AM, Jason Blevins notifications@github.com wrote:

Thanks for this patch. I just got around to applying and testing it and it looks fine to me. I did make one small change: I used the same face for checkboxes as was used for list markers. Also, I think it's fine to enable this in markdown-mode. Here is the commit: 4121324.

Great!

One more thing: if you could write a test case or two to add to tests/markdown-test.el, that would be very helpful. I will close this issue now, so please just start a new pull request if you want to add some tests.

Ok. I haven’t written tests for emacs before so this will be a learning experience. I’m busy for the next week but hope to get to it after that.

Howard

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

No branches or pull requests

2 participants