Skip to content

A package to rotate text and party with parrots at the same time

License

Notifications You must be signed in to change notification settings

positron-solutions/parrot

Repository files navigation

Parrot https://cultofthepartyparrot.com/parrots/parrot.gif

Animated pet parrot for your modeline. This fork includes Org TODO and magit push integration to reward your hard work.

parrot_in_action.gif

Installation & Configuration

This repository is a fork and not yet reflected in MELPA. Be sure to get this version if you want this programming interface and behavior.

(use-package parrot
  ;; This package is not yet the version in MELPA, so you will need to explicitly specify it.
  ;; :straight '(parrot :type git :host github :repo "positron-solutions/parrot")
  :elpaca  (parrot :host github :repo "positron-solutions/parrot" :files (:defaults "img"))

  :custom
  (parrot-type 'emacs) ; see parrot types below
  (parrot-animate 'hide-static) ; hides after animation

  ;; A selection of default values.  M-x customize-group parrot to see full list of options
  ;; (parrot-animate-on-load t) ; do animation after load (also startup)
  ;; (parrot-rotate-animate-after-rotation t) ; enable animation on included rotation commands
  ;; (parrot-party-on-org-todo-states '("DONE"))
  ;; (parrot-party-on-magit-push t)

  (parrot-mode t)) ; enable the global minor mode!

M-x parrot-start-animation or click on the parrot to watch it animate.

Contents

Animation Behavior

  • parrot-animation-frame-interval - seconds between animation frames; can be a decimal number.
  • parrot-minimum-window-width - minimum width of the window, below which party parrot mode will be disabled.
  • parrot-animate - ='animate to enable parrot animation, 'no-animation for a static image, 'hide-static to only show while animating.
  • parrot-animate-on-load - animate when mode started no matter other settings.
  • parrot-spaces-before - number of spaces of padding before the parrot.
  • parrot-spaces-after - number of spaces of padding after the parrot.
  • parrot-num-rotations - number of times the parrot will cycle through its gif.

Available Parrots

By default, after a rotation is performed, the selected parrot in the modeline will start rotating. You may select your desired parrot interactively with M-x parrot-set-parrot-type to preview.

Like the wonders of the ancient world, parrot comes in 7 original flavors:

ParrotName
https://i.imgur.com/53YCmpd.gifdefault
https://i.imgur.com/svleFy1.gifconfused
https://i.imgur.com/DSExpFD.gifemacs
https://i.imgur.com/xpUahDq.gifnyan
https://i.imgur.com/BnSpEwK.gifrotating
https://i.imgur.com/fMf23JR.gifscience
https://i.imgur.com/WmXn4wz.gifthumbsup

Adding animations

There are many ways to incorporate animation into your daily life.

  • Add #'parrot-start-animation to hooks
  • Add advice to arbitrary functions
  • Add a command or function to the parrot click hook
  • Add a process filter and animate while the process is running

Hooks

For example, if you want the parrot to animate whenever you receive mail in mu4e, you can try:

(add-hook 'mu4e-index-updated-hook #'parrot-start-animation)

Org Todo state hook

By default, the org-after-todo-state-change-hook has parrot--todo-party added so that if the org-state is in parrot-party-on-org-todo-states, animation will occur.

Advice

If no hook is available, just add an advice to a function or command:

(advice-add #'jinx-correct :after #'parrot-start-animation)

Parrot click hook

You can also add functions to parrot-click-hook so they will run whenever you click on the parrot.

(add-hook 'parrot-click-hook 'flyspell-buffer)

Calling parrot-start-animation with t will also run forever until you run parrot-stop-animation, and then will stop after parrot-num-rotations more.

Processes

By default, magit-push will animate the parrot until the process sentinel stops it. This is configured by the custom variable parrot-party-on-magit-push.

Check out the parrot--maybe-advise-magit-push for an example of how to advise a function that returns a process to add an extra sentinel to that process, allowing you to party on any process!

The parrot-party-while-process function can be used to animate any arbitrary process that will finish with a process sentinel.

Rotation command configuration

This section covers the rotate commands and behavior. Try the command parrot-rotate-prev-word-at-point on the string “start” to preview the behavior.

Rotation keybindings

Use parrot-rotate-next-word-at-point and parrot-rotate-prev-word-at-point to rotate words at point. If a match is not found under the cursor, parrot will hunt for the nearest match in the current whitespace-delimited word and rotate it.

;; for vanilla emacs
(global-set-key (kbd "C-c p") 'parrot-rotate-prev-word-at-point)
(global-set-key (kbd "C-c n") 'parrot-rotate-next-word-at-point)

;; for evil users
(define-key evil-normal-state-map (kbd "[r") 'parrot-rotate-prev-word-at-point)
(define-key evil-normal-state-map (kbd "]r") 'parrot-rotate-next-word-at-point)

Rotation dictionary

Parrot uses a dictionary list that defines word rotations. You can override the default by setting parrot-rotate-dict in your init file. A sample one is provided below:

(setq parrot-rotate-dict
      '(
        (:rot ("alpha" "beta") :caps t :lower nil)
        ;; => rotations are "Alpha" "Beta"

        (:rot ("snek" "snake" "stawp"))
        ;; => rotations are "snek" "snake" "stawp"

        (:rot ("yes" "no") :caps t :upcase t)
        ;; => rotations are "yes" "no", "Yes" "No", "YES" "NO"

        (:rot ("&" "|"))
        ;; => rotations are "&" "|"

        ;; default dictionary starts here ('v')
        (:rot ("begin" "end") :caps t :upcase t)
        (:rot ("enable" "disable") :caps t :upcase t)
        (:rot ("enter" "exit") :caps t :upcase t)
        (:rot ("forward" "backward") :caps t :upcase t)
        (:rot ("front" "rear" "back") :caps t :upcase t)
        (:rot ("get" "set") :caps t :upcase t)
        (:rot ("high" "low") :caps t :upcase t)
        (:rot ("in" "out") :caps t :upcase t)
        (:rot ("left" "right") :caps t :upcase t)
        (:rot ("min" "max") :caps t :upcase t)
        (:rot ("on" "off") :caps t :upcase t)
        (:rot ("prev" "next"))
        (:rot ("start" "stop") :caps t :upcase t)
        (:rot ("true" "false") :caps t :upcase t)
        (:rot ("&&" "||"))
        (:rot ("==" "!="))
        (:rot ("." "->"))
        (:rot ("if" "else" "elif"))
        (:rot ("ifdef" "ifndef"))
        (:rot ("int8_t" "int16_t" "int32_t" "int64_t"))
        (:rot ("uint8_t" "uint16_t" "uint32_t" "uint64_t"))
        (:rot ("1" "2" "3" "4" "5" "6" "7" "8" "9" "10"))
        (:rot ("1st" "2nd" "3rd" "4th" "5th" "6th" "7th" "8th" "9th" "10th"))
        ))

The following labels are provided for defining rotations in a dictionary entry:

  • :upcase t will add UPPER CASE rotations
  • :caps t will add Capitalized rotations
  • :lower nil will exclude lowercase rotations
  • If no labels are provided, the word list will default to lowercase rotations
  • Defining a word list for which there are no rotations will result in an error, e.g. (:rot ("yes" "no") :lower nil).

You can also append to the default dictionary:

(dolist (entry '((:rot ("hakuna" "matata"))
                 (:rot ("peeple" "sheeple"))))
  (add-to-list 'parrot-rotate-dict entry))

Rotation behavior

  • parrot-rotate-hunt-for-words - t to rotate words that aren’t directly under the cursor.
  • parrot-rotate-jump-to-word-after-hunt - t to jump to the word rotated if it isn’t under the cursor.
  • parrot-rotate-animate-after-rotation - t to animate the party parrot after rotating a word.
  • parrot-rotate-highlight-after-rotation - t to highlight a word after rotating.
  • parrot-rotate-start-char-invalid-regexp - regexp used to determine if parrot shouldn’t start a rotation.
  • parrot-rotate-start-bound-regexp - regexp used to find the start bound to search for rotations.
  • parrot-rotate-end-bound-regexp - regexp used to find the end bound to search for rotations.

Acknowledgments

d12 wrote the original version of this package. I decided to fork it mainly for independence. As d12 credits many, so do I credit d12 and many for enabling this package to reach its current form.

All parrots including the gifs in this README (with the exception of emacs parrot) were taken from @jmhobbs Cult of the Party Parrot site. Thanks to @mermop (default), @kyprifog (confused), @shiruken (science), @vaicine (nyan), @youngcba3 (rotating), @zeftilldeath (thumbsup parrot) for their respective parrots, and of course @jmhobbs for compiling them.

Thanks to @francoislg for Party Parrot as a Service, with which d12 created the emacs parrot.

Thanks to Aaron Hawley, from whom d12 borrowed a good deal of their rotation code. You can see his rotate text implementation on emacswiki.

Thanks to @rejeep for ecukes, an excellent Cucumber-like testing framework.

Thanks to @DamienCassou for his detailed and thoughtful code review comments.

A special thanks to @TeMPOral, without which parrot wouldn’t be possible. d12 heavily modified the source code of nyan-mode to create parrot spawn. All credit goes to him for paving the way to new heights of mode-line distraction.

parrot3cat.png