понедельник, 16 января 2012 г.

Emacs и style guide

У нас на работе для части (основной) С++ кода поменялся style guide - добавлися pre-commit hook, который запрещает коммитить файлы, в которых  есть пробелы в конце строки. Оказалось что в моем любимом emacs справиться с данной напастью оказалось очень легко. Помог отличный пакет
show-wspace, который уже был установлен. Осталось только добавить строку
(add-hook 'c-mode-common-hook 'show-ws-highlight-trailing-whitespace)

и вуаля - все проблемные строки сразу подсвечиваются.

Все настройки для emacs можно найти тут:
emacs-configuration (сам файл для посдветки пробелов находится тут: ai/colorize.el

up.
Как мне напомнили в комментах (спасибо Ваня!) можно еще автоматически удалять пробелы при сохранении файла. Сделать это только для С/С++ режима можно так:
(add-hook 'c-mode-common-hook
      (lambda()
        (add-hook 'local-write-file-hooks
              '(lambda()
                 (save-excursion
                   (delete-trailing-whitespace))))))

воскресенье, 15 января 2012 г.

Новый способ ведения блога

Купил BlogPress для iPad - вроде на первый взгляд удобно. Будем надеяться, что это поможет реанимировать блог - благо многое прочитал и многое написал - есть что рассказать. Всех с наступившим НГ!



понедельник, 10 января 2011 г.

Процесс программирования с псевдокодом

Совершенный код рекламирует подход к написанию функций называемый "Процесс программирования с псевдокодом". Упрощенная суть его в том, что в начале описывается работа функции в виде обычного текста, а затем этот текст преобразуется в комментарии и под каждым из них записывается реальный код. Плюс данного подхода заключается в том, что значительно упрощается процесс написания сложной функции, и к тому же она сразу получается хорошо задокументированной. В процессе реального использования данного подхода я понял, что мне не хватает возможности по преобразованию моего описания функции в комментарий с сохранением отступов. В результате в моем конфигурационном файле emacs я написал следующий код:


(defun my-ppp-comment-region (top bottom)
  ""
  (interactive "r")
  (setq macro [home ?\M-m ?\C-z ?/ ?\C-z ?/ ? ])
;;  (apply-macro-to-region-lines top bottom macro
  (save-excursion
    (let ((end-marker (copy-marker bottom))
          next-line-marker)
      (goto-char top)
      (if (not (bolp))
          (forward-line 1))
      (setq next-line-marker (point-marker))
      (while (< next-line-marker end-marker)
        (goto-char next-line-marker)
        (save-excursion
          (forward-line 1)
          (set-marker next-line-marker (point)))
        (unless (looking-at "[ \t]*$")
            (save-excursion
              (let ((mark-active nil))
                (execute-kbd-macro (or macro last-kbd-macro)))))
        );;while
      (set-marker end-marker nil)
      (set-marker next-line-marker nil))))

и затем добавил
(define-key c-mode-base-map (kbd "C-M-;") 'my-ppp-comment-region)

в
c-mode-common-hook

например так:

(defun my-c-mode-common-hook ()
  ;; включить режимы auto-newline и hungry-delete
  (c-toggle-auto-hungry-state 1)
  (flyspell-prog-mode);;включаем проверку правописания в комментариях и строках 
  (ispell-change-dictionary "american")
  ;; работает как C-j  
  (define-key c-mode-base-map "\C-m" 'c-context-line-break)
  ;;добавлеям комментарии для Проектирования с Помощью Псевдокода
  (define-key c-mode-base-map (kbd "C-M-;") 'my-ppp-comment-region)
  ...
)
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

в результате по C-M-; мое описание волшебным образом превращается в готовый комментарий к функции.

прагматизм

Недавно закончил читать "Программист-прагматик" Ханта и Томаса - книгу, которую многие рекомендовали прочитать.
Одним словом: понравилось. Книга написана простым и приятным языком. Освещен широкий круг вопросов от использования vcs, до способов определения требований проекта. Книга сильно перекликается с Совершенным кодом Макконелла и тот кто читал последнюю найдут в этой книге не очень много нового. Но повторить еще раз отличные советы никогда не бывает вредно, так о потраченном времени я нисколько не жалею. К тому же эта книга подтолкнула меня вступить в ACM с этого года - посмотрим сколько нового я успею узнать через эту организацию :).

улучшение compile-mode в emacs

В программировании важны мелочи. Хочется не тратить время на рутинные операции. Необходимо, чтобы инструмент которым ты пользуешься стал продолжением твоей руки - ее неотделимой частью и тогда многие операции будут делаться фактически автоматически. Пусть экономия может составлять пару секунд, но если это делается десятки раз в день, то может получиться солидный бонус.

Для меня таким инструментом, стал emacs. И операцией, которую мне всегда хотелось улучшить - была компиляция. Связка: "сохранить текст + скомпилировать/собрать и запустить тесты" выполняется мною в день очень часто и оптимизировать ее очень хотелось.

Чего хочется добиться:


  • автоматически сохранять все буфера перед началом компиляции: это избавит нас от надоедливых вопросах о необходимости сохранить измененные буфера
  • в некоторых каталогах проектов над которыми я работаю используются makefile из каталогов верхнего уровня: хочется, что бы при компиляции автоматически происходил поиск нежного файла - это избавит от необходимости переключаться на другой буфер перед компиляцией
  • хочется что бы после успешного завершения компиляции/тестирования окно compile автоматически закрывалось, а при ошибках оставалось бы для  дальнейших разбирательств
  • компиляцию и тестирование запускать различными комбинациями клавиш
Вооружившись следующими ссылками:

получилось следующее решение, удовлетворяющее вышеозначенным требованиям:

(defun upward-find-file (filename &optional startdir)
  "Move up directories until we find a certain filename. If we
  manage to find it, return the containing directory. Else if we
  get to the toplevel directory and still can't find it, return
  nil. Start at startdir or . if startdir not given"

  (let ((dirname (expand-file-name
 (if startdir startdir ".")))
(found nil) ; found is set as a flag to leave loop if we find it
(top nil))  ; top is set when we get
   ; to / so that we only check it once

    ; While we've neither been at the top last time nor have we found
    ; the file.
    (while (not (or found top))
      ; If we're at / set top flag.
      (if (string= (expand-file-name dirname) "/")
 (setq top t))
      
      ; Check for the file
      (if (file-exists-p (expand-file-name filename dirname))
 (setq found t)
; If not, move up a directory
(setq dirname (expand-file-name ".." dirname))))
    ; return statement
    (if found dirname nil)))


;; Helper for compilation. Close the compilation window if
;; there was no error at all.
(setq compilation-finish-functions 'compile-autoclose)
(defun compile-autoclose (buffer string)
  (cond ((and 
          (string-match "finished" string) 
          (not (string-match "*grep*" (buffer-name (get-buffer buffer)))))
         (bury-buffer "*compilation*")
         (winner-undo)
         (message "Build successful."))
        (t                                                                    
         (message "Compilation exited abnormally: %s" string))))

;;функция сохраняет содержимое всех буферов
;;и затем вызывает make из католога где находится текущий файл
(defun my-compile-file ()
  "Save all files and compile"
    (interactive)
    (save-some-buffers 1)
    (let ((default-directory (or (upward-find-file "Makefile") ".")))
      (compile (format "cd %s && make -k -j8" default-directory))
      )
  )

;; support for compile tests
(defun my-compile-tests-file ()
  "Save all files and compile"
    (interactive)
    (save-some-buffers 1)
    (let ((default-directory (or (upward-find-file "Makefile") ".")))
      (compile (format "cd %s && make -k -j8 check" default-directory))
      )
  )
;;устанавливаем нашу функцию
(global-set-key  [f7] 'my-compile-file)
(global-set-key  [(shift f7)] 'my-compile-tests-file)

Из недостатков:
если во время компиляции/тестирования переключать окна, то после успешного завершения процесса состояние окон может вернуться в другое состояние, что было перед началом процесса. В идеале было бы конечно создавать новое окно для компиляции, но тут надо разбираться дальше.

вторник, 28 декабря 2010 г.

моя конфигурация emacs

Опубликовал свою текущую конфигурацию emacs:

https://github.com/ai81/emacs-configuration.

Она представляет собой клон конфигурации

http://eschulte.github.com/emacs-starter-kit/

которая в свою очередь является переработкой в стиле литературного программирования конфигурации

http://github.com/technomancy/emacs-starter-kit/.

Я несколько переработал  оригинал убрав найденные конфликты, добавив свои настройки (например для erlnag) и значительно расширив поддержку C++/C -  в частности интегрирован cedet. Так же много добавлено для git.

Тестировалась на паре linux - на win требует доработки (если будет время, то сделаю). Может кому пригодится.

воскресенье, 28 ноября 2010 г.

Обзор книги "Объектно-ориентированное конструирование программных систем"

Итак это свершилось. Рубеж пройден. Самая лучшая книга по ОО-программированию изучена от корки до корки. Книга старая - автор (Бертран Мейер) писал ее в середине 90-х, а перевели ее на русский поти через 10 лет - в 2005.

Но как не странно книга не устарела. Мейер пишет о ОО методе полностью погрузившись в проблему.  Книга составлена следующим образом: в начале очерчивается проблема, производится ее анализ, потом происходит попытка создать несколько вариантов решения проблемы и в конце выбирается лучший подход, по мнению автора. Таким образом основы метода подробно освещены, что будет особенно полезно для новичков.

Освещены все важные темы: АТД, типизация, наследование, исключения, универсализация (шаблоны в С++), управление памятью. Особенное место занимает Проектирование по Контракту -книга считается фундаментальным трудом на эту тему.

Часто когда я читал проскакивала мысль - как же без это штуки я живу в контексте С++?! это просто не возможно! И почему язык Eiffel (который создал Мейер и на котором написано большинство примеров из книги) так и не стал по настоящему популярным? Может быть у него были неудачные реализации? Может быть его синтаксис, напоминающий pascal, является громоздким? Может быть он закрыт? Или может просто он появился не в свое время и эта ниша была уже намертво занята такими монстрами как C++ и Java (которых поддерживали огромные корпорации). Вообще мир не справедлив.

В общем эту книгу поздно я прочитал - надо было в 2005, у лучше в 90-x на английском...

Из недостатков: книга огромная, тяжело постоянно таскать с собой, что бы читать в транспорте; библиография зачем то вынесена на диск - очень не удобно.

p.s.
Поставил среду Eiffel Studio- неплохая IDE, хотя не emacs конечно, и даже под linux x64 отлично работает. Эх, что же помешало этому языку по настоящему зажечь? Вроде же автор делал все правильно...