" nil t)
306 | (when (search-forward-regexp " ]*>\\(\\(.*?\n?\\)*\\) " nil t)
307 | (let ((str (match-string 1)))
308 | (with-temp-buffer
309 | (erase-buffer)
310 | (insert str)
311 | (goto-char (point-min))
312 | (howdoi-replace-html-ahref-tags)
313 | (html2text)
314 | (howdoi-strip-html-tags '("code"))
315 | (setq result (buffer-substring
316 | (point-min)
317 | (point-max))))))))
318 | result))
319 |
320 | (defun howdoi-stackoverflow-retrieve-answer ()
321 | "Retrieve an answer from the stackoverflow."
322 | (goto-char (point-min))
323 | (let ((result '()))
324 | (while (search-forward-regexp "]*?class=\"answer" nil t)
325 | (when (search-forward-regexp " " nil t)
326 | (when (search-forward-regexp " \\(\\(.*?\n?\\)*\\) " nil t)
327 | (let ((str (match-string 1)))
328 | (with-temp-buffer
329 | (erase-buffer)
330 | (insert str)
331 | (goto-char (point-min))
332 | (howdoi-replace-html-ahref-tags)
333 | (html2text)
334 | (howdoi-strip-html-tags '("code"))
335 | (setq result (append result `(,(buffer-substring (point-min) (point-max))))))))))
336 | result))
337 |
338 | (defun howdoi-strip-html-tags (tags)
339 | "Strip given html TAGS."
340 | (dolist (tagn tags)
341 | (dolist (tag `(,(format "<%s>" tagn) ,(format "%s>" tagn)))
342 | (goto-char (point-min))
343 | (while (search-forward tag nil t)
344 | (replace-match "" nil t)))))
345 |
346 | (defun howdoi-stackoverflow-retrieve-code-snippets ()
347 | "Retrieve code snippets from the stackoverflow."
348 | (goto-char (point-min))
349 | (let ((result '()))
350 | (while (search-forward-regexp "]*?class=\"answer" nil t)
351 | (if (search-forward-regexp " ]*>" nil t)
352 | (when (search-forward-regexp "\\([^<]*?\\) " nil t)
353 | (let ((str (match-string 1)))
354 | (setq result (append result `(,str)))))
355 | (when (search-forward-regexp "\\(.*?\\) " nil t)
356 | (let ((str (match-string 1)))
357 | (setq result (append result `(,str)))))))
358 | result))
359 |
360 | (defun howdoi-show-next-question ()
361 | "Show next question. The purpose of this function to use it in
362 | the *How do I* pop up buffer to view next question."
363 | (interactive)
364 | (setq howdoi-display-callback 'howdoi-pop-answer-to-buffer-callback)
365 | (setq howdoi-current-question-num (+ howdoi-current-question-num 1))
366 | (when (> howdoi-current-question-num 10)
367 | (setq howdoi-current-question-num 10))
368 | (howdoi-stackoverflow-request (nth howdoi-current-question-num
369 | howdoi-question-urls)))
370 |
371 | (defun howdoi-show-current-question ()
372 | "Pop up a buffer named *How do I* displaying the current found
373 | question. It may be helpful to use after such command as
374 | `howdoi-query-line-at-point-replace-by-code-snippet' to view more
375 | details in a pop up buffer or to find more preferable code
376 | snippet."
377 | (interactive)
378 | (let* ((url (nth howdoi-current-question-num howdoi-question-urls))
379 | (cache (gethash url howdoi-requests-cache)))
380 | (if cache
381 | (howdoi-pop-answer-to-buffer (nth 0 cache) (nth 1 cache))
382 | (message "Current question not found"))))
383 |
384 | (defun howdoi-show-previous-question ()
385 | "Show previous question. The purpose of this function to use it in
386 | the *How do I* pop up buffer to view previous question."
387 | (interactive)
388 | (setq howdoi-display-callback 'howdoi-pop-answer-to-buffer-callback)
389 | (setq howdoi-current-question-num (- howdoi-current-question-num 1))
390 | (when (< howdoi-current-question-num 0)
391 | (setq howdoi-current-question-num 0))
392 | (howdoi-stackoverflow-request (nth howdoi-current-question-num
393 | howdoi-question-urls)))
394 |
395 | (defun howdoi-browse-current-question ()
396 | "Ask a WWW browser to open current question."
397 | (interactive)
398 | (let ((url (nth howdoi-current-question-num howdoi-question-urls)))
399 | (browse-url url)))
400 |
401 | ;;;###autoload
402 | (define-minor-mode howdoi-minor-mode
403 | "Toggle howdoi minor mode.
404 |
405 | With a prefix argument ARG, enable Line Number mode if ARG is
406 | positive, and disable it otherwise. If called from Lisp, enable
407 | the mode if ARG is omitted or nil.
408 |
409 | This minor mode provides a set of key bindings for easy access to
410 | the howdoi.
411 |
412 | The following keys are available in `howdoi-minor-mode':
413 |
414 | key binding
415 | ------- -----------
416 |
417 | C-c C-o n howdoi-show-next-question
418 | C-c C-o p howdoi-show-previous-question
419 | C-c C-o c howdoi-show-current-question
420 | C-c C-o b howdoi-browse-current-question
421 | C-c C-o u howdoi-query
422 | C-c C-o l howdoi-query-line-at-point
423 | C-c C-o r howdoi-query-line-at-point-replace-by-code-snippet
424 | C-c C-o i howdoi-query-insert-code-snippet-at-point"
425 | :lighter " HowDoI"
426 | :keymap (let ((map (make-sparse-keymap)))
427 | (define-key map (kbd "C-c C-o n") 'howdoi-show-next-question)
428 | (define-key map (kbd "C-c C-o p") 'howdoi-show-previous-question)
429 | (define-key map (kbd "C-c C-o c") 'howdoi-show-current-question)
430 | (define-key map (kbd "C-c C-o b") 'howdoi-browse-current-question)
431 | (define-key map (kbd "C-c C-o u") 'howdoi-query)
432 | (define-key map (kbd "C-c C-o l") 'howdoi-query-line-at-point)
433 | (define-key map (kbd "C-c C-o r") 'howdoi-query-line-at-point-replace-by-code-snippet)
434 | (define-key map (kbd "C-c C-o i") 'howdoi-query-insert-code-snippet-at-point)
435 | map)
436 | :group 'howdoi)
437 |
438 | (define-derived-mode howdoi-mode special-mode "HowDoI"
439 | "Howdoi major mode. This major mode is mainly intended to
440 | provide key bindings for easy navigation within a pop up buffer."
441 | :group 'howdoi)
442 |
443 | (define-key howdoi-mode-map (kbd "n") 'howdoi-show-next-question)
444 | (define-key howdoi-mode-map (kbd "p") 'howdoi-show-previous-question)
445 | (define-key howdoi-mode-map (kbd "b") 'howdoi-browse-current-question)
446 | (define-key howdoi-mode-map (kbd "u") 'howdoi-query)
447 |
448 |
449 | (provide 'howdoi)
450 |
451 | ;;; howdoi.el ends here
452 |
--------------------------------------------------------------------------------
| |