Source

emacs-blogger / blogger-mode.el

Full commit
;; Variables
(defvar blogger-mode-map nil "Local keymap for dired-mode buffers.")
(defvar blogger-username nil "Username used to log in")
(defvar blogger-password nil "Password to log in")
(defvar blogger-default-blog-name nil "Default blog to edit")

(defvar blogger-initialized nil "Check if the initialization procedure was successful")

(defvar blogger-path "~/workspace/emacs-blogger" "Emacs blogger path")
;; Faces
(defface blogger-date
  '((t (:inherit file-name-shadow))) "Face for date displaying")
(defface blogger-title
  '((t (:inherit font-lock-function-name-face))) "Face for displaying blog titles")
(defface blogger-tags
  '((t (:inherit font-lock-variable-name-face))) "Face for displaying tags")


;; Pymacs initialization
(require 'pymacs)
(add-to-list 'pymacs-load-path blogger-path)
(pymacs-load "blogger_bridge" "blogger-bridge-")


(defun blogger-post ()
  "Generic function to upload a post in blogger, it determines
the current major mode and do exporting in various forms"
  (interactive)
  
  (when (not blogger-initialized)
    (blogger-initialize))

  (let (title id)
    (setq title (read-from-minibuffer "Title: "))
    (setq blogger-buffer-title title)
    ;; The blogger-bridge-post return id of the post yet posted.
    (setq blogger-buffer-post-id (blogger-bridge-post title (blogger-filter-content)))
    (message (format "Post '%s' successfully posted" title))
    )
  )

(defun blogger-initialize ()
  "Initialize the blogger object with authentication and fetching of blogs/entires"
  (blogger-authenticate)
  (blogger-bridge-refresh)
  (if blogger-default-blog-name
      (blogger-set-blog blogger-default-blog-name)
    (blogger-select-blog)
    )
  (setq blogger-initialized t)
  )

(defun blogger-prompt-entry ()
  "Prompt an entry by name in the current blog, how to handle duplicate titles? mabye with numbers appended by recentness"
  )

(defun blogger-update-post ()
  "Update a blog post"
  (interactive)
  (let (id title content)
    (setq id blogger-buffer-post-id)
    (setq title blogger-buffer-title)
    (setq content (blogger-filter-content))
    (blogger-bridge-update-post id title content)
    (message "Post successfully updated")
    )
  )

;; Filtering
(defun blogger-filter-content ()
  "Filter the content of the current buffer and return the result of the filtering"
  (case major-mode
    ('rst-mode        
     (blogger-process-rst))
    ('org-mode
     (blogger-process-org))
    )
  )

(defun blogger-filter (filters)
  "Filter the current buffer with the filters passed in"
  (let (buffer-substring-filters)
    (setq buffer-substring-filters filters)
    (filter-buffer-substring (point-min) (point-max))))

(defun blogger-process-rst ()
  "Filter the current buffer and return a string of the bloggerized post"
  (blogger-filter '(blogger-bridge-rst2blogger))
  )

(defun blogger-process-org ()
  "org-mode->pseudo html for blogger"
  (save-excursion 
  (org-export-region-as-html (point-min) (point-max) t 'string))
  )

;; Mode Commands
(defun blogger-show ()
  "Starts a buffer with the blogs listed and shows the entries of
  each blog, in Blogger mode"
  (interactive)

  (when (not blogger-initialized)
    (blogger-initialize))

  (pop-to-buffer (generate-new-buffer "Blogger"))
  
  (let ((buffer-read-only nil))
    (blogger-create-bloglist))
  
  (blogger-mode)
  )

(defun blogger-delete ()
  "Delete post under cursor"
  (interactive)
  (let (post-id)
    (setq post-id (get-text-property (point) 'entry-id))
    
    (when (and post-id (y-or-n-p "Delete Post?"))
      (blogger-bridge-delete-post post-id)
      (blogger-bridge-refresh)
      (blogger-update-view)
      (message "Entry successfully deleted"))
    )
  )

(defun blogger-tag ()
  "Tag post under cursor"
  (interactive)
  ;; Getting the post-id
  (let (post-id taglist)
    (setq post-id (get-text-property (point) 'entry-id))
    
    (blogger-bridge-tag-post
     post-id  
     (split-string (read-from-minibuffer "Insert tags separated by commas: ") ","))

    (blogger-bridge-refresh)
    (blogger-update-view)
    )
  )
(defun blogger-rename-post ()
  "rename post under the cursor"
  (when (get-text-property (point) 'post-id)
    (blogger-bridge-update-title (get-text-property 'blog-id) (get-text-property 'post-id)))
  (blogger-update-view))

(defun blogger-update-view ()
  "Refill the buffer with info about the blog"
  (interactive)
  (save-excursion
    (let ((buffer-read-only nil))
      (erase-buffer)
      (blogger-create-bloglist)
      )
    )
  )

(defun blogger-quit ()
  "quit the blogger buffer"
  (interactive)
  (when (eq major-mode 'blogger-mode)
    (kill-buffer (current-buffer))))


;; Utility/Displaying functions
(defun blogger-authenticate ()
  "authenticate to blogger system"
  (when (not (or blogger-username blogger-password))
    (blogger-prompt-usn-pass))
  
  (when (not (blogger-bridge-authenticate))
    ;; Reset the value of the blogger username and password
    (setq blogger-username nil)
    (setq blogger-password nil)
    (error "Invalid username/password"))
  )

(defun blogger-prompt-usn-pass ()
  "Define the blogger-username variable and blogger-password variable"
  (interactive)
  (setq blogger-username (read-from-minibuffer "Username: "))
  (setq blogger-password (read-passwd "Password: "))
  )

(defun blogger-select-blog ()
  "Ask the user for the blog and set the current blog"
  (interactive)
  (blogger-set-blog (blogger-prompt-blog))
  )

(defun blogger-prompt-blog ()
  "Prompt the user for a blog with completion support"
  (setq blogger-default-blog-name 
	(completing-read "Select a Blog (TAB for completion): " (blogger-bridge-get-blog-names))
  ))

(defun blogger-set-blog (blog-name)
  "Set the blog specified by BLOG-NAME as the current edited blog"
  (interactive)
  (blogger-bridge-set-current-blog-by-name blog-name))

(defun blogger-create-bloglist ()
  "Create the list of entries in the selected blog"
  (dolist (entry (blogger-bridge-get-entries)) 
    ;; Unpack the entry in various parts
    (let ((etitle (nth 1 entry))
	  (eid (nth 0 entry))
	  (edate (nth 2 entry))
	  (entry-tags (nth 3 entry)))
      
      ;; Insert date
      (insert (propertize (concat "-" edate "  ") 'face 'blogger-date))
      (insert (propertize (concat etitle "  ") 'face 'blogger-title))
      ;; If there are tags
      
      (cond 
       ;; If entry-tags is nil do nothing
       ((eq entry-tags nil) (insert ""))
       ;; If it is a string insert the string alone
       ((stringp entry-tags) (insert entry-tags))
       ;; If it is a list insert the tags separated by :
       ((sequencep entry-tags)
	(insert 
	 (propertize
	  (mapconcat 'identity entry-tags ":") 'face 'blogger-tags)))
       )
      
      ;; Apply entry-id property to text
      (put-text-property (line-beginning-position)
			 (line-end-position) 'entry-id eid)
      (insert (propertize "\n" 'entry-id eid))
      )
    ) ;; End dolist blogs
  )
  

;; Misc
(defun blogger-upload-image (filename)
  "Upload an image to the album Blogger in picasa web albums using the same blogger account"
  (interactive "fSelect an Image: ")
  (blogger-prompt-usn-pass)
  
  (let (url)
    (setq url (blogger-bridge-upload-image filename))
    (kill-new url)
    (message "C-y to paste the uploaded image URL")
    )
  )

;; Making a keymap!!!
(let ((map (make-keymap)))
  (suppress-keymap map)
  ;; Commands to mark or flag certain categories of files
  (define-key map "d" 'blogger-delete)
  (define-key map "g" 'blogger-update-view)
  (define-key map "q" 'blogger-quit)
  (define-key map "t" 'blogger-tag)
  (setq blogger-mode-map map))


(defun blogger-mode ()
  "Mode for watching the blogs in blogger(?)"
  (interactive)

  ;; After that there are some conventions

  ;; Adding the local variables
  (kill-all-local-variables)
  ;; Setting the major mode
  (setq major-mode 'blogger-mode)
  ;; Pretty name in the mode line
  (setq mode-name "Blogger Mode")
  (use-local-map blogger-mode-map)
  (setq buffer-read-only t)  
  )