SIGCSE 2017 - a path to github part 2


Just for some quick context. The process I started to describe in the last post and continue here chronicles what I did at Stuy with high schoolers. Now that I'm at Hunter college, I'm adapting the process but the overarching themes remain the same.

Post starts here:

Now that your students have been pulling the classcode repo regularly it's time to move to the next step - adding and pushing files to a repo.

I don't claim to do this the "right way" or the best way but it's worked for me and it's gotten my students up to speed.

I ease my students into adding and pushing files using git through homework submission. I create a single repo, usually named submissions and make a folder for each student underneath looking something like this:

└── submissions
    ├── abram_sarah
    ├── chen_stuart
    └── thompson_steve

Before going any further, let me clear up one thing. The repo is public so all the students have access to each others work. I'm OK with that. We could have each student make their own repo and use git submodules to make a submissions repo but administration is much trickier and we lose the chance to build a culture of cooperation and trust. We can lock down our submission systems as much as we want. If students want to share assignments there's nothing we can do about it.

My preference is to try to build a culture that minimizes bad behavior and rewards good behavior. I'd rather see an incorrect homework so that I can tell what we need to work on than a copied perfect assignment. I'd rather see students cite each other, share properly, and support each other than copy in the shadows.

I'm not naive enough to believe that copying doesn't happen in my classes but I still prefer erring on the side of openness.

Once the repo is set up, I give all the students access. This is a little onerous since I have to type each of their GitHub usernames under the collaborators section of the submissions repo but I only have to do this once a semester.

Then I teach the workflow. Assignments go into a file or folder under their directory named ##_name where ## is the assignment number (01,02,03, etc) and name is the assignment name. The student workflow is:

  1. git pull
  2. git add (sometimes)
  3. git commit
  4. git push

Since every student is working in their own directory, things basically work.

The first issue that students come up with is when another student pushes before another student. The second student merely has to do another git pull before proceeding. This provides an easy introduction to dealing with the distributed nature of git.

There will occasionally be other issues when students don't follow procedure exactly so I'll have to fix the repo every now and then but nothing too bad and each time is a opportunity to show the class:

  1. you can pretty much always restore and fix things once you commit them.
  2. the specifics to fix things.

There will be a few bumps in the road but after a few assignments the sailing will be pretty smooth.

At the end of the day, the students are a little closer to being fully fluent using git, they're hopefully using each others code as resources but in a proper way and since the students are all using a consistent assignment naming convention I can use simple scripts and shell commands to do all sorts of processing on assignments.

That's the end of phase two. The next step brings us to small projects using git.

SIGCSE 2017 - a path to github part 1

Both at and prior to SIGCSE 2017, I promised to write up the steps I take to introduce and use revision control systems in my classes.

This series is not meant to be a git or GitHub tutorial. There are plenty of those already (two of which I've linked to below). This is about the process I use with my students to get them up to speed.

As with any new tool, there will be some resistance but once git saves them once, they get religion. There will also be some bumps in the road but at the end of the day, the students will be using a valuable and necessary tool.

I was also surprised at the ancillary benefits I got as a teacher by using GitHub in particular. I'll talk about that at the end of the series.

Here's part one.

I'm doing this with git and GitHub but there's no reason why other systems and hosts can't be used. I'd also recommend that any educator or student sign up for the assorted discounts offered by GitHub.

I've followed this basic idea multiple times and done it over the course of a single semester, a year, and even two years. Regardless of time frame, the idea is the same. Make each step simple and relevant and introduce complexity and roadblocks a piece at a time.

Step 1 - code distribution

To start, I don't even talk about version control. We start with code distribution. For years, I've looked for efficient ways of sharing code with my classes. Both code developed in class and code for assignments.

I've tried things like NFS, Dropbox, online code repositories like the files section of systems like Moodle or Blackboard.

At Stuy, we've always had efficiency problems with NFS and Dropbox has multiple problems ranging from students not being able to install the client on school machines to the problems of the network hit when a room full of kids are syncing at the same time.

Uploading to a CMS system was also problematic - I'm a command line wonk and hate going through slow web page menus to navigate a filesystem and upload files. I also had to remember to get the files off of whatever machine I was working on in class and then transfer them to the CMS when I had a free moment.

Enter git. Now, of course, if you're going to use git in the classroom you have to know it. There are plenty of resources out there. Online courses, articles, videos, and tutorials. Here are a couple:

I also want to point out that I just use raw command line git along with native GitHub. GitHub has rolled out GitHub Classroom which adds a layer of support for educators. I don't use it because, as I said, I'm an old school command line wonk and also because I figured out a sequence that worked for me and my students before GitHub Classroom existed. Were I starting now, I'd take some time to look at their current offerings before jumping in.

Set up

Before starting, make sure you register your ssh keys. This help page has more information. You'll want to register an ssh key from every machine you use - home, work, laptop.

Now go over to GitHub and make a new repository. I usually name it classcode. BEGINNER NOTE: when creating the repo, make sure to check the "initialize this repository with a README" box. If you don't you'll be given a set of instructions on how to set things up once you click Create repository but it's easier and easier to follow if you start with an initialized repo with a README.

I make the repo public – it's code I'm distributing – nothing to hide here. If you aren't comfortable with that, just make the repo private. If you've registered as a teacher with GitHub, you can set up an organization and you'll be able to set up free private repos within it. The other downside here is that you'll have to individually give each student access to the repo. That's a mild annoyance but it only has to be done once.

Teacher use

Next, clone out the repo. BEGINNER NOTE: Make sure you check out the ssh version not the https version. Just make sure that when you click the clone button, it says "Clone with SSH." If not, just click the "Use SSH" link in the same box. Students will clone the using https.

From the teacher point of view, you can just start using the repo. My work flow is typically:

  1. git pull at the start of class
  2. write code throughout class
  3. git add, git commit, and git push at the end of class

I use a similar flow when I want to add files in my office or at home.

Student use

From the student point of view, assuming a public repo, they just have to clone the repo and at the beginning of every class or work session, do a git pull. That's all there is to it.


That's it. The kids are now using GitHub – they're probably looking at and poking around on the web site as well as pulling files to their machines. You can also, in class, show things like git status, git log, and git diff to set the stage for step 2 of this process and beyond.

Since the students aren't adding, committing or pushing, you probably won't get any errors.

The only problem that could reasonably occur is if a student places a file in their local copy of the repo with the same name as something they haven't pulled yet. This is pretty easy to address and provides a nice stepping stone lesson to again, set the stage for more complex operations.

I'm happy with this as a first step towards git using GitHub. It provides a nice way of sharing class code while gently introducing the students to the tool.

The next step is having the students add files to a repo. That's the next post in this series.

SIGCSE 2017 - Recap

As a high school teacher, I was never able to attend SIGCSE, the conference of the ACM's Special Interest Group on Computer Science Education. Between the number of instructional days I would lose and the cost, I could never justify going. Instead I looked over the proceedings and read many of the papers.

Now that I'm at Hunter, I was finally able to attend. This year in Seattle, the conference ran from Wednesday through Saturday. I was part of a panel on "Tools we can't live without." Over the next few weeks, I hope to blog about a number of things I thought and talked with people about over the conference including:

  • The path I use to teach git and why GitHub a good teaching tool (my talk).
  • The relationship of different CS Ed stakeholders - teachers, researchers, organizations, etc.
  • Teaching at the high school level vs college - perceptions and reality.
  • The challenges of tech tool adoption in schools.
  • What's going on in K12 CS Certification.
  • Maybe some other stuff.

Today, some overall thoughts.

The good

As with many conferences, the "hallway track" along with receptions sponsored by the CS4All consurtium, TEALS, were terrific. I was able to finally meet in person many people who I've only known virtually and got to know many more as well. I left the conference with a much larger address book and a long list of follow up items. Being in Seattle, I also enjoyed being able to spend time with people from TEALS and, two of the CS Ed groups working hard to do some real good (yes - I do like and support these guys even though I call them out on things I disagree with, but that's the subject of another post).

I attended sessions on CS certification, teacher preparation, assessments, POGIL based instruction to name a few. They ranged from valuable to interesting and to be honest, a couple of "what were they thinking" but the overall experience was very much worth the trip. I also got to speak to a number of wonderful students at the poster sessions.

The keynotes are also well worth a read (sorry if you don't have ACM digital library access). Jeannette Wing talked about the importance of probability and statistics in CS Ed, and aspects of Gail Chapman's talk "Inspire, Innovate, and Improve…" keynote and Mitch Resnick's "Fulfilling Papert's Dream" both spoke to the educator inside me.

The bad

The biggest downside to me was that I found very little value added in a number of the paper sessions over just reading the papers. Part of this is probably because of my own over-inflated expectations given the number of years I've waited to attend. Part of it though, was the fact that sessions were so tightly packed that I didn't have time to follow up with presenters before having to run to the next thing. Unfortunately, in some cases, it was because the presenter merely "read" the paper much as a professor sometimes just reads the slides or the book to his class.

Other thoughts

One paper presentation I very much liked was Exam Wrappers: Not a Silver Bullet presented by Michelle Craig and Ben Stephenson. I actually came in late since I was hustling over from the lunch. The result was that I didn't actually know what "Exam Wrappers" were until well after the talk when I ran into Jim Huggins. Exam wrappers, in short, are merely when you require the students fill out something for some credit when picking up their exams. The funny thing is that it's a strategy that high school teachers have used for years without a special name and we already knew the good and bad of it without the research but that's not what I want to get at here. What I loved about the talk, besides the fact that Ben and Michelle are clearly strong presenters is that this was a negative result that was being presented. I also loved the fact that they didn't present their research as gospel but rather pointed out the strengths and weaknesses of their approach - they made a case to what and why we should pay attention to and what should be taken with a grain of salt.

This was a major breath of fresh air after being exposed to so much education 'research' over the course of my life that the author or presenter felt was just as strong as a mathematical proof rather than an indication based on a specific experience or small set of experiences.

I also felt a little weird at times during the week when west coast people seemed to know me. I know I'm a loud mouthed curmudgeon and I go on my periodic ed rants but given the dearth of comments on this blog I was really surprised to get as many as "great to meet you in person after reading your blog" or "we know you and your work" all week. It was weird and somewhat humbling.

Finally, another highlight f`or me was that I got to catch up with some of family.


Already planning to submit something to present at SIGCSE 2018 in Baltimore.


Tomorrow morning I fly out to Seattle for SIGCSE 2017. For those of you not in the CS Education space, SIGCSE is the ACM (Association for Computing Machinery) special interest group for computer science education.

I've wanted to go for years but have never been able. It's hard for a high school teacher to miss a week in mid March, particularly in places with a school calendar similar to New York. NY city schools are already closed for a week in February and then Spring Break is right around the corner. If you're teaching an AP course with the exam in early May, losing a week in March is really not an option. Even if you can take the time, you'll probably have to foot the bill out of pocket.

Now that I'm at Hunter, I've got more flexibility in terms of schedule and attending is probably even more important given my current roles.

I'm looking forward to the talks and events but probably even more looking forward to seeing old friends, meeting new ones and seeing face to face friends that til now I've only known through the web.

On Saturday I'll be part of a panel (thanks Ria) titled "Tools we can't live without." I'll probably talk about the way I use git and GitHub and how I get my students up to speed but there are lots of tools I can talk about.

I plan to write up a series of posts on how I use GitHub (and how it evolved from other versioning systems) as well as thoughts about other tools I've used and some I've struggled with.

If you're going to be at SIGCSE drop me a line, I'd love to connect.

Whiteboard interviews

A few days ago, I saw a piece on David Heinemeier Hansson's tweet on whiteboard interviews:

I'm not a huge fan of the whiteboard interview but I think many of the tweets missed the point. Most of the whiteboard interviews I'm aware of involve algorithmic problem solving while the tweets, at least the ones I've seen all refer to things that indeed one would look up. Things like API calls - not things that whiteboard interviewers typically care about.

Tim Bray takes that point of view and shared his thoughts in a recent blog post.

The idea behind the whiteboard interview isn't all bad. The interviewer has an opportunity to see how the candidate thinks and works through a problem and in an ideal situation the interviewer is, at least to a point, coaching the candidate to help them through the process. It seems to me that the problem lies more in the types of questions asked and the skill of the interviewer rather than the idea that candidates work through a problem live.

I'd imagine that whiteboard interview success skew towards candidates who work well in isolation in a short period of time, have a good amount of exposure to these types of algorithmic problems. Also those who have practiced and trained specifically for the interview will have a huge edge. For people new to the process, it can be very stressful.

Once a candidate has accepted a position, they'll likely be working with a team, with additional resources, and with time to solve problems. This is a very different environment. The whiteboard interview, much like the SAT is thus something of an arbitrary gatekeeper that a candidate must prepare for and conquer rather than a skill that they must develop that will make them a more productive team member.

This whole process tends to advantage those with the time and background to prepare - this is one of the places where the argument that whiteboard interview hurt diversity come from.

I could be totally wrong but I seem to recall that the whiteboard interview, at least in terms of external visibility grew out of the legendary Google puzzle interview questions.

A tech giant like Google can interview however they like and they'll still get the talent. They go to the most selective institutions where candidates have already been culled for success. If they then interview 100 candidates and 10 of them would be good fits, as long as a couple thrive through the whiteboard interview process, they'll get their engineer. They'll miss out on a lot of great talent but they can cast such a large net they'll fill there seats with productive employees.

On the other hand, smaller companies will certainly miss out on great talent if they follow the same approach.

Is there a better way?

Some companies pre-assign mini projects and then discuss that at the interview. Pairing could also be a lower stress alternative to the technical interview. Another option would be to look at a candidates existing projects.

An interesting question is "why do so many companies use the whiteboard interview?" I can't say for certain but I wouldn't be surprised if it was a simple as "because Google does it."

For over 100 years, Stuyvesant high school required students study mechanical drawing (drafting). The relevance of the subject lessened over the decades and what was taught in many ways has become a joke. A typical class during the CAD parts of the class might be going over the cylinder command in CadKey. That's like spending a day studying the edit menu in Microsoft Word in an English class. If you can't tell, I'm not a fan. Drafting at Stuyvesant is the vestigial organ of the course of study.

My point isn't to bash drafting at Stuy but rather that there have been any number of schools that require their students take drafting even though it doesn't prepare students for, nor lead them to anything else in the schools curriculum (which now can be said for Stuy's drafting requirement). I've spoken to teachers and principals at these schools and we go back and forth as I press them for the reason for the requirement and ultimately, they tell me that their school requires drafting "because Stuyvesant does."

Why do so many small companies employ the whiteboard interview? Because the big kids do. The trouble is that the big kids can get away with it, the smaller players on the other hand, are hurting themselves. Even the bigger players would be well served to try to come up with an interview process that better assesses fit rather than a course filter that while it does pull in talent misses talent as well.

Using Emacs - 32 - C++

This video is specifically for my students or any students out there who are starting with C++ and emacs. The videos also longer than usual, coming in at a little over 20 minutes.

The big difference is instead of building on my existing config, the code at the bottom is a complete standalone configuration. It's all pulled from the main config with one additional package.

By taking the code at the bottom and putting in into a file named init.el in a directory off of your home directory named .emacs.d and run emacs, it will install everything and you'll be good to go.

If you've been following this series, the only new package is ggtags and the configuration code is:

;; tags for code navigation
(use-package ggtags
  :ensure t
  (add-hook 'c-mode-common-hook
	    (lambda ()
	      (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
		(ggtags-mode 1))))

For people new to the series, the top section sets up the emacs package manager. After that we install:

Package Description
which-key brings up contextual key binding help
auto-complete just as the name says
flycheck in line, live syntax checking
yasnippet snippets and expansion
ggtags source code navigation
moe-theme just because

The video also show me using counsel-ag which is part of the swiper/counsel package. You can check that out here as well as some other packages I use like smartparens, hungry-delete and probably a few more.

You can look at my complete configuration or the other videos for details.

If you're an experienced C++ developer and use emacs, please share tips, tricks, and suggestions. I haven't done serious C++ work in over a decade and while I did professional development in C in a past life, never in C++.

The packages used here are not C++ specific - I use them for Java, Python, Clojure, and Javascript development as well.

Here's the configuration code:

;; set up package sources
(require 'package)
(setq package-enable-at-startup nil)
(add-to-list 'package-archives
	     '("melpa" . ""))

;; Bootstrap `use-package'
(unless (package-installed-p 'use-package)
  (package-install 'use-package))

;; small interface tweaks
(setq inhibit-startup-message t)
(tool-bar-mode -1)
(fset 'yes-or-no-p 'y-or-n-p)
(global-set-key (kbd "<f5>") 'revert-buffer)

;; bring up help for key bindings
(use-package which-key
  :ensure t 

;; Auto completion
(use-package auto-complete
  :ensure t
    (global-auto-complete-mode t)

;; on the fly syntax checking
(use-package flycheck
  :ensure t
  (global-flycheck-mode t))

;; snippets and snippet expansion
(use-package yasnippet
  :ensure t
  (yas-global-mode 1))

;; tags for code navigation
(use-package ggtags
  :ensure t
  (add-hook 'c-mode-common-hook
	    (lambda ()
	      (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
		(ggtags-mode 1))))

;; Theme
(use-package color-theme
  :ensure t)
(use-package moe-theme
  :ensure t)


Using Emacs - 31 - elfeed part 3 - macros

In part 2 I talked about how I used Hyrdas to quickly navigate through elfeed tags. It was a nice step up but the fact that I still had to manually edit my configuration code for every new tag to update the hydra was a problem.

Basically, I had to somehow or other, take a list of all the active tags and with it build a defhydra command that will then make my Hydra.

Fortunately, emacs, being a lisp, has macros. I'm not talking about keyboard macros which I talked about in episode 15 but rather Lisp style macros. Macros let you transform code and then execute the transformed code.

The example I give in the video:

(defmacro infix (a op b)
  `(,op ,a ,b))

(infix 3 + 8) ; evaluates to 11

This transforms the 3+8 into (+ 3 8) and then evaluates it to be 11.

We can use this idea with our Hydra.

We can use the call elfeed-db-get-all-tags to get a list of all the tags in our database. I decided that if I had an uppercase letter in the tag, I'd use the lowercase version of that letter as my "hotkey" and if it didn't, I'd just use the first letter.

So, given a tag list of:

(active blogs cs eDucation emacs local misc sports star tech unread webcomics)

I'd want a "hotkey" of b for logs and d for eDucation.

The routine z/hasCap tests to see if a tag has a capital letter in it and z/get-hydra-option-key returns the final "hotkey:"

(defun z/hasCap (s) ""
       (let ((case-fold-search nil))
       (string-match-p "[[:upper:]]" s)

(defun z/get-hydra-option-key (s)
  "returns single upper case letter (converted to lower) or first"
  (let ( (loc (z/hasCap s)))
    (if loc
	(downcase (substring s loc (+ loc 1)))
      (substring s 0 1)

mz/make-elfeed-cats takes a list of tags and returns a list of items where each item is in the form expected by the hydra definition:

("t" (elfeed-search-set-filter "@6-months-ago +tagname") "tagname")
(defun mz/make-elfeed-cats (tags)
  "Returns a list of lists. Each one is line for the hydra configuratio in the form
     (c function hint)"
  (mapcar (lambda (tag)
	    (let* (
		   (tagstring (symbol-name tag))
		   (c (z/get-hydra-option-key tagstring))
	      (list c (append '(elfeed-search-set-filter) (list (format "@6-months-ago +%s" tagstring) ))tagstring  )))

Finally, here's our macro:

(defmacro mz/make-elfeed-hydra ()
  `(defhydra mz/hydra-elfeed ()
     ,@(mz/make-elfeed-cats (elfeed-db-get-all-tags))
     ("*" (elfeed-search-set-filter "@6-months-ago +star") "Starred")
     ("M" elfeed-toggle-star "Mark")
     ("A" (elfeed-search-set-filter "@6-months-ago") "All")
     ("T" (elfeed-search-set-filter "@1-day-ago") "Today")
     ("Q" bjm/elfeed-save-db-and-bury "Quit Elfeed" :color blue)
     ("q" nil "quit" :color blue)

The line that starts with *,@* calls the routine that builds lines of code for all the tags in the database and the macro leaves me with the defhydra I need.

I then redefine the hydra every time I need it, just in case tags changed:

(defun mz/make-and-run-elfeed-hydra ()

and bind mz/make-and-run-elfeed-hydra to j and J in my elfeed keymap (this code goes in the bind section of my use-package elfeed section):

("j" . mz/make-and-run-elfeed-hydra)
("J" . mz/make-and-run-elfeed-hydra)

As long as I remember to name my tags in a way that they don't conflict with one another I can quickly navigate all around elfeed.

Macros FTW!!!!

Here's the video:


Will we lose CS teachers to industry?

If we properly prepare CS teachers, won't they just jump ship and take tech industry jobs?

I hear that a lot.

Tech pays big. Teaching? Not so much. Tech workers are respected and have flexible jobs. Teaching? Again, not so much.

Those chanting these refrains advocate the current simple teacher "training" - scripted lessons, minimal pedagogical content knowledge, even less real content knowledge. That will keep them in the classroom.

They're wrong.

People fearing an exodus of prepared CS teachers don't get education. True, many young CS teachers will leave the profession but that's because many young teachers leave the profession. Why do young teachers leave? Regardless of subject area some of the reasons are:

  • It's much harder than everyone thinks it is
  • Low pay
  • Lack of respect
  • Overworked
  • Lack of autonomy
  • Being scapegoated for poverty
  • It's become about testing, not teaching

None of these are unique to computer science teachers so the argument that CS teachers who know too much will leave is really saying, "we have to keep our teachers dumb enough to stay - make sure they don't have outside options" rather than "let's make teaching a desirable profession to be in."

Of course, this is bred from a lack of understanding about what drives teachers. It's typical of politicians and business leaders and short term temps like TFAers who came in for a cup of coffee and now know how to solve the education problem.

Teacher don't become teachers to get rich or to do better than the other guy – I know I didn't. We enter it to do good - to uplift the have nots. This is why business models like stack ranking and bonus or merit pay just don't work. A school is a team and we're all in it together. Our job is to take care of our kids, not to be better than that other guy. We wish we had more time to work together and to improve things for our entire population.

Back to computer science.

My contention is that you might lose some teachers to industry but they either weren't meant to be teachers anyway or they couldn't afford to be teachers or the system beat them down. None of these are reasons not to properly prepare them. Besides, all teachers in all subject areas could work their way into an entry level tech job via a summer coding boot camp.

We can also look to the past to allay concerns. While it's true that for hiring purposes, English teachers are a dime a dozen and candidates typically have fewer outside options (although great English teachers are harder to find), Math and Science teachers generally have options. I know many top Math and Science teachers who could easily get non teaching jobs - the Math teachers in finance the science, certainly in pharmaceutical companies over in NJ. These options exist yet we manage to populate our classes with teachers. True, it's difficult at times, particularly in Physics, but these are due to the lack of respect teaching gets as a profession.

If we prepare CS teachers properly, yes, we'll lose some, but we'll keep the ones we're supposed to or if we lose them it will be due to other factors. Additionally, by having proper CS teacher preparation programs, we'll also provide an entry path to those people meant to be teachers but prior had no way of getting in.

As a nation, we're moving away from prepared, knowledgeable teachers and towards drill-masters. Let's not let CS Education go the way of all ed.

Using Emacs - 30 - elfeed part 2 - Hydras

In part 1, I talked about elfeed, a really awesome feed reader for emacs. Generally, I'm really liking it but there's been one problem - not being able to navigate quickly between groups of feeds with a keystroke or two.

It's emacs so there has to be a solution.

Enter hydra - a terrific emacs package from the same guy who brought us swiper, another one of my favorite emacs packages.

Basically, Hydra allows us to create Hydras - a collection of emacs commands tied o a single prefix along with a nice interface and help system.

Truth be told, I don't use hydra as much anymore since which-key does such a great job most of the time. Which-key, however, is no help here.

Here's the code to install hydra along with a some of sample Hydra's I use:

(use-package hydra 
  :ensure t)

;; Hydra for modes that toggle on and off
 (kbd "C-x t")
 (defhydra toggle (:color blue)
   ("a" abbrev-mode "abbrev")
   ("s" flyspell-mode "flyspell")
   ("d" toggle-debug-on-error "debug")
   ("c" fci-mode "fCi")
   ("f" auto-fill-mode "fill")
   ("t" toggle-truncate-lines "truncate")
   ("w" whitespace-mode "whitespace")
   ("q" nil "cancel")))

;; Hydra for navigation
 (kbd "C-x j")
 (defhydra gotoline 
   ( :pre (linum-mode 1)
	  :post (linum-mode -1))
   ("t" (lambda () (interactive)(move-to-window-line-top-bottom 0)) "top")
   ("b" (lambda () (interactive)(move-to-window-line-top-bottom -1)) "bottom")
   ("m" (lambda () (interactive)(move-to-window-line-top-bottom)) "middle")
   ("e" (lambda () (interactive)(end-of-buffer)) "end")
   ("c" recenter-top-bottom "recenter")
   ("n" next-line "down")
   ("p" (lambda () (interactive) (forward-line -1))  "up")
   ("g" goto-line "goto-line")

;; Hydra for some org-mode stuff
 (kbd "C-c t")
 (defhydra hydra-global-org (:color blue)
   ("t" org-timer-start "Start Timer")
   ("s" org-timer-stop "Stop Timer")
   ("r" org-timer-set-timer "Set Timer") ; This one requires you be in an orgmode doc, as it sets the timer for the header
   ("p" org-timer "Print Timer") ; output timer value to buffer
   ("w" (org-clock-in '(4)) "Clock-In") ; used with (org-clock-persistence-insinuate) (setq org-clock-persist t)
   ("o" org-clock-out "Clock-Out") ; you might also want (setq org-log-note-clock-out t)
   ("j" org-clock-goto "Clock Goto") ; global visit the clocked task
   ("c" org-capture "Capture") ; Don't forget to define the captures you want
   ("l" (or )rg-capture-goto-last-stored "Last Capture"))

Take a look at the Hydra home page for detailed information.

With Hydra installed, I can creat one for navigating in elfeed:

`(defhydra mz/hydra-elfeed ()
   ("c" (elfeed-search-set-filter "@6-months-ago +cs") "cs")
   ("e" (elfeed-search-set-filter "@6-months-ago +emacs") "emacs")
   ("d" (elfeed-search-set-filter "@6-months-ago +education") "education")
   ("*" (elfeed-search-set-filter "@6-months-ago +star") "Starred")
   ("M" elfeed-toggle-star "Mark")
   ("A" (elfeed-search-set-filter "@6-months-ago") "All")
   ("T" (elfeed-search-set-filter "@1-day-ago") "Today")
   ("Q" bjm/elfeed-save-db-and-bury "Quit Elfeed" :color blue)
   ("q" nil "quit" :color blue)

and add a binding to the elfeed key map:

(use-package elfeed
  :ensure t
  :bind (:map elfeed-search-mode-map
	      ("q" . bjm/elfeed-save-db-and-bury)
	      ("Q" . bjm/elfeed-save-db-and-bury)
	      ("m" . elfeed-toggle-star)
	      ("M" . elfeed-toggle-star)
	      ("j" . mz/hydra-elfeed/body)
	      ("J" . mz/hydra-elfeed/body)))

This isn't the actual Hydra I use – we'll get to that in the next installment where I'll show how to make a Hydra on the fly that contains keys for all your elfeed tags but this is a reasonable example.

Here's the video:


Using Emacs - 29 -elfeed part 1

Since the demise of Google Reader, I've been using Feedly to read my streams. Feedly's a nice product and it's been working well for me for quite some time.

A few days ago, I decided to see what emacs had to offer on the feed reader front. One solution was Gnus but then I've never been able to get my head around Gnus. Another was elfeed.

I thought I'd give elfeed a go.

Combined with elfeed-goodies and elfeed-org it's a pretty nice solution. You can easily search by either keywords or tags and tags are particularly easy to set up with elfeed-org.

If I want to display all the items from the last month, I hit s (for search) and enter the query:


For only unread posts:

@6-months-ago +unread

For unread posts tagged emacs:

@6-months-ago +unread +emacs

And for everything in the past 24 hours, read or not:


It's pretty easy and pretty slick. The only thing missing is easy single key navigation. There's one solution to that problem over at Pragmatic Emacs and I'll present another one in the next two posts.

I'm using some of the code from pragmatic emacs (the functions that start with bjm) which makes things easier when sharing the elfeed database on Dropbox (see the Pragmatic Emacs post above for details) and also a couple of routines I found via web search).

Here's my basic configuration:

(setq elfeed-db-directory "~/Dropbox/shared/elfeeddb")

(defun elfeed-mark-all-as-read ()

;;functions to support syncing .elfeed between machines
;;makes sure elfeed reads index from disk before launching
(defun bjm/elfeed-load-db-and-open ()
  "Wrapper to load the elfeed db from disk before opening"

;;write to disk when quiting
(defun bjm/elfeed-save-db-and-bury ()
  "Wrapper to save the elfeed db to disk before burying buffer"

(defalias 'elfeed-toggle-star
  (elfeed-expose #'elfeed-search-toggle-all 'star))

(use-package elfeed
  :ensure t
  :bind (:map elfeed-search-mode-map
	      ("q" . bjm/elfeed-save-db-and-bury)
	      ("Q" . bjm/elfeed-save-db-and-bury)
	      ("m" . elfeed-toggle-star)
	      ("M" . elfeed-toggle-star)

(use-package elfeed-goodies
  :ensure t

(use-package elfeed-org
  :ensure t
  (setq rmh-elfeed-org-files (list "~/Dropbox/shared/")))

Check out elfeed and make sure to go to the links provided on the main elfeed page.


Enter your email address:

Delivered by FeedBurner

Google Analytics Alternative