「.emacs」を含む日記 RSS

はてなキーワード: .emacsとは

2026-08-15

は?まだVS Codeとか使ってんの?ウケるんだけど(笑)

画面の半分くらいよくわからないアイコンと親切ぶったサイドバーで埋まってんの、見るからに重たいしダサくない?

GUIボタンポチポチマウスクリックして「プログラミング楽しい〜」とか、マジで小学生知育アプリレベルで止まってて草なんだよね。

Vimキーバインド拡張機能とか入れて満足してそうだけど、それただの偽物だから

見た目だけイキったハリボテでドヤられても困るんだよね。

 

本気でコード書きたいなら、黙ってEmacs一択から

カーソル移動のためにいちいちマウスに手を伸ばすとか人生タイパ悪すぎるし、Emacsならホームポジションから指先1ミリも動かさずにすべて完結するわけ。

てかさ、VS Codeってただのコード編集ソフトでしょ?

EmacsエディタじゃなくてOSから

メールファイル管理も端末操作も、なんならOrg-modeタスク管理論文執筆も全部Emacsの中で動くの。

他人が作った拡張機能をありがたがってダウンロードするだけのVS Codeユーザーと違って、こっちはEmacs Lispで自分の好きなように挙動を書き換えて自分専用の最強環境に育て上げてんのね。

 

いつまで初心者向けおすすめエディタみたいな記事に騙されてVS Codeメモリ無駄食いしてんの?

メモリGB食えば気が済むわけ?

さっさとターミナル開いてapt install emacsして.emacsと向き合いなよ。

沼にハマって自分の手で最強の環境作れるようになってから、初めてエンジニアって名乗ってよね。

俺のemacs設定

;;; ~/.emacs --- Development settings -*- lexical-binding: t; -*-

;;; Package management

(require 'package)

;; Keep the built-in GNU ELPA archive and add NonGNU ELPA and MELPA.
(add-to-list 'package-archives
             '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)

(package-initialize)

(defconst my/required-packages
  '(web-mode
    js2-mode
    typescript-mode
    php-mode
    cython-mode
    jinja2-mode
    cyberpunk-theme)
  "Packages required by this configuration.")

;; Install only missing packages.  A network failure must not prevent Emacs
;; from starting; the failed package is simply reported in *Messages*.
(let (missing-packages)
  (dolist (pkg my/required-packages)
    (unless (package-installed-p pkg)
      (push pkg missing-packages)))

  (when missing-packages
    (condition-case err
        (package-refresh-contents)
      (error
       (message "Package archive refresh failed: %s"
                (error-message-string err))))

    (dolist (pkg (nreverse missing-packages))
      (unless (package-installed-p pkg)
        (condition-case err
            (package-install pkg)
          (error
           (message "Package installation failed (%s): %s"
                    pkg (error-message-string err))))))))

;;; Cyberpunk theme

(when (package-installed-p 'cyberpunk-theme)
  (condition-case err
      (progn
        ;; A theme is global, so this applies to every major mode.
        (mapc #'disable-theme custom-enabled-themes)
        (load-theme 'cyberpunk t))
    (error
     (message "Could not load cyberpunk theme: %s"
              (error-message-string err)))))

;;; Python and Cython

(defun my/call-formatter (program arguments file log-buffer)
  "Run PROGRAM with ARGUMENTS on FILE, writing output to LOG-BUFFER.
Signal an error when the process does not exit successfully."
  (let ((exit-code
         (apply #'call-process
                program nil log-buffer nil
                (append arguments (list file)))))
    (unless (and (integerp exit-code) (zerop exit-code))
      (error "%s failed with exit code %s; see %s"
             program exit-code (buffer-name log-buffer)))))

(defun my/replace-buffer-from-file (file)
  "Replace the current buffer contents with FILE."
  (let ((formatted-buffer (generate-new-buffer " *python-formatted*")))
    (unwind-protect
        (progn
          (with-current-buffer formatted-buffer
            (insert-file-contents file))
          (if (fboundp 'replace-buffer-contents)
              (replace-buffer-contents formatted-buffer)
            ;; Compatibility fallback for older Emacs versions.
            (let ((old-point (point)))
              (erase-buffer)
              (insert-file-contents file)
              (goto-char (min old-point (point-max))))))
      (kill-buffer formatted-buffer))))

(defun my/python-format-buffer ()
  "Format the entire Python/Cython buffer with isort and autopep8.

Each formatter is used only when its executable is present in `exec-path'.
The autopep8 E501 rule is ignored, so autopep8 does not enforce the
79-character line-length limit.  Changes are applied only after every
available formatter exits successfully."
  (interactive)
  (let ((isort-program (executable-find "isort"))
        (autopep8-program (executable-find "autopep8")))
    ;; Missing commands are deliberately ignored.
    (when (or isort-program autopep8-program)
      (save-restriction
        (widen)
        (let* ((source-directory
                (and buffer-file-name
                     (file-name-directory buffer-file-name)))
               (temporary-file-directory
                (if (and source-directory
                         (file-writable-p source-directory))
                    source-directory
                  temporary-file-directory))
               (suffix (if (derived-mode-p 'cython-mode) ".pyx" ".py"))
               (temp-file
                (make-temp-file "emacs-python-format-" nil suffix))
               (log-buffer (get-buffer-create "*Python formatter*"))
               (coding-system-for-write buffer-file-coding-system)
               (coding-system-for-read buffer-file-coding-system))
          (unwind-protect
              (progn
                (with-current-buffer log-buffer
                  (erase-buffer))

                (write-region (point-min) (point-max)
                              temp-file nil 'silent)

                ;; Import sorting first, then PEP 8 whitespace cleanup.
                (when isort-program
                  (my/call-formatter
                   isort-program '("--quiet") temp-file log-buffer))

                (when autopep8-program
                  (my/call-formatter
                   autopep8-program
                   '("--in-place" "--ignore=E501")
                   temp-file log-buffer))

                (my/replace-buffer-from-file temp-file)
                (message "Python formatting completed"))
            (when (file-exists-p temp-file)
              (delete-file temp-file))))))))

(defun my/python-editing-setup ()
  "Common setup for Python and Cython buffers."
  (setq-local indent-tabs-mode nil)
  (when (boundp 'python-indent-offset)
    (setq-local python-indent-offset 4))
  (local-set-key (kbd "C-c C-r") #'my/python-format-buffer))

(add-hook 'python-mode-hook #'my/python-editing-setup)
(add-hook 'python-ts-mode-hook #'my/python-editing-setup)
(add-hook 'cython-mode-hook #'my/python-editing-setup)

(autoload 'cython-mode "cython-mode" "Major mode for Cython." t)
(add-to-list 'auto-mode-alist '("\\.pyx\\'" . cython-mode))
(add-to-list 'auto-mode-alist '("\\.pxd\\'" . cython-mode))
(add-to-list 'auto-mode-alist '("\\.pxi\\'" . cython-mode))

;;; Web development modes

(autoload 'web-mode "web-mode" "Major mode for web templates." t)
(autoload 'js2-mode "js2-mode" "Major mode for JavaScript." t)
(autoload 'typescript-mode "typescript-mode" "Major mode for TypeScript." t)
(autoload 'php-mode "php-mode" "Major mode for PHP." t)
(autoload 'jinja2-mode "jinja2-mode" "Major mode for Jinja2 templates." t)

;; Add the generic PHP rule first.  More specific *.blade.php and template
;; rules are prepended afterwards and therefore take priority.
(add-to-list 'auto-mode-alist '("\\.php\\'" . php-mode))
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.blade\\.php\\'" . web-mode))

(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.xhtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.shtml\\'" . web-mode))

(add-to-list 'auto-mode-alist '("\\.css\\'" . css-mode))
(add-to-list 'auto-mode-alist '("\\.scss\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.less\\'" . web-mode))

(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
(add-to-list 'auto-mode-alist '("\\.mjs\\'" . js2-mode))
(add-to-list 'auto-mode-alist '("\\.cjs\\'" . js2-mode))
(add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode))

;; React: web-mode handles JSX and TSX.
(add-to-list 'auto-mode-alist '("\\.jsx\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode))

;; Other common web-template/component files supported by web-mode.
(add-to-list 'auto-mode-alist '("\\.vue\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.svelte\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.twig\\'" . web-mode))

;; Explicit Jinja2 suffixes.  Files such as page.html.j2 are also covered.
(add-to-list 'auto-mode-alist '("\\.j2\\'" . jinja2-mode))
(add-to-list 'auto-mode-alist '("\\.jinja\\'" . jinja2-mode))
(add-to-list 'auto-mode-alist '("\\.jinja2\\'" . jinja2-mode))

(with-eval-after-load 'web-mode
  (add-to-list 'web-mode-engines-alist
               '("blade" . "\\.blade\\.php\\'"))
  (add-to-list 'web-mode-content-types-alist
               '("jsx" . "\\.\\(jsx\\|tsx\\)\\'")))

(defun my/insert-two-spaces ()
  "Insert exactly two spaces."
  (interactive)
  (insert "  "))

(defun my/web-editing-setup ()
  "Disable automatic indentation and make TAB insert two spaces."
  (setq-local indent-tabs-mode nil)
  (setq-local tab-width 2)
  (setq-local standard-indent 2)
  (setq-local electric-indent-chars nil)

  ;; web-mode also has its own auto-indent-on-yank switch, independent of
  ;; Emacs electric indentation.
  (when (boundp 'web-mode-enable-auto-indentation)
    (setq-local web-mode-enable-auto-indentation nil))

  ;; Keep any manually invoked indentation command at two spaces, even though
  ;; TAB itself is deliberately changed into literal space insertion.
  (dolist (variable
           '(sgml-basic-offset
             css-indent-offset
             js-indent-level
             js2-basic-offset
             typescript-indent-level
             c-basic-offset
             web-mode-markup-indent-offset
             web-mode-css-indent-offset
             web-mode-code-indent-offset
             web-mode-attr-indent-offset))
    (when (boundp variable)
      (set (make-local-variable variable) 2)))

  (when (fboundp 'electric-indent-local-mode)
    (electric-indent-local-mode -1))
  (when (fboundp 'electric-layout-local-mode)
    (electric-layout-local-mode -1))

  ;; php-mode is based on CC Mode, which has another independent electric
  ;; indentation mechanism for characters such as ; and }.
  (when (derived-mode-p 'php-mode)
    (when (fboundp 'c-toggle-auto-newline)
      (c-toggle-auto-newline -1))
    (when (fboundp 'c-toggle-electric-state)
      (c-toggle-electric-state -1)))

  ;; Prevent mode-specific RET commands from indenting the next line.
  (local-set-key (kbd "RET") #'newline)
  (local-set-key (kbd "<return>") #'newline)

  ;; TAB must insert two literal spaces, not run an indentation command.
  (local-set-key (kbd "TAB") #'my/insert-two-spaces)
  (local-set-key (kbd "<tab>") #'my/insert-two-spaces))

(dolist (hook
         '(web-mode-hook
           html-mode-hook
           mhtml-mode-hook
           css-mode-hook
           css-ts-mode-hook
           js-mode-hook
           js2-mode-hook
           js-ts-mode-hook
           typescript-mode-hook
           typescript-ts-mode-hook
           tsx-ts-mode-hook
           php-mode-hook
           jinja2-mode-hook))
  (add-hook hook #'my/web-editing-setup))

;;; .emacs ends here
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages nil))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

2025-02-03

Emacs廃人ライフ

俺のEmacsライフは、もはやただのエディタを超えて、完全に生活のものだ。

日常のあらゆる側面がEmacs支配されていて、他のソフトウェアなんて目にも入らねぇ。

今日は、どれだけ俺がこの深淵世界に没頭しているか、そのレベルを見せてやるぜ。

1. 自作パッケージLispの力

俺の.emacs.dには、数十種類どころか、もう百を超える自作パッケージが眠ってる。

特に自分で書いたLisp関数は、日々のタスク自動化するために欠かせねぇ。

例えば、特定フォルダ内のMarkdownファイル自動HTMLに変換してブラウザで表示するスクリプトを組んじまった。

これでブログを書くたびに手間いらずで、「C-c C-v」でプレビューできる快感は、もう中毒だぜ。

サンプルLispコード
(defun my-markdown-to-html ()
  "MarkdownファイルHTMLに変換してブラウザで表示する関数"
  (interactive)
  (let ((markdown-file (read-file-name "Markdownファイル選択: ")))
    (shell-command (format "pandoc %s -o %s.html" markdown-file (file-name-sans-extension markdown-file)))
    (browse-url (concat (file-name-sans-extension markdown-file) ".html"))))

この関数を使えば、Markdownファイルを選んで一発でHTMLに変換し、そのままブラウザで表示できる。これがなきゃブログなんて書けないぜ。

2. Org-modeによる人生管理

Org-modeは俺の人生のものだ。TODOリストスケジュール管理だけじゃなくて、プロジェクト管理文書作成まで全てを一元化してる。

特にカスタムキャプションプロパティドロップダウンメニューを駆使して情報整理に命懸けてるんだ。

さらに、Org Babel使ってRやPythonコードを直接実行しながらデータ分析なんて日常茶飯事だ。この機能のおかげで、データサイエンスEmacs内で完結しちまうからたまんねぇよ。

3. キーバインドマクロ神業

俺のキーバインド設定は他者には理解不能レベルだ。

自分専用にカスタマイズしたショートカットが数百種類もあるんだぜ。

「M-p」で過去コミットメッセージを呼び出す機能なんか、Gitとの連携が一瞬でできるから開発効率が飛躍的に向上する。

さらに、Emacsにはマクロ機能があるから自分操作を記録して再生することもできる。

この前、自分専用のマクロを作って、特定フォーマットドキュメントを一瞬で整形することができた。

これで「お前は本当に人間なのか?」って言われてもおかしくないレベルだ。

4. Emacs Lispによる拡張

Emacs Lispを書くことが俺の日常になってる。この前、自分だけのコード補完システムを構築したばかりだ。

この機能のおかげで、特定キーワード入力すると関連するコードスニペットが自動的に提案される仕組みになってるからコーディング中に思考が途切れることなスムーズに進行するぜ。

コード補完システムサンプル
(defun my-auto-complete ()
  "カーソル位置に基づいてコードスニペットを提案する"
  (interactive)
  (let ((input (thing-at-point 'symbol)))
    (if input
        (let ((completion-list '("myFunction" "myVariable" "myClass")))
          (setq completion-list
                (cl-remove-if-not
                 (lambda (item) (string-prefix-p input item))
                 completion-list))
          (if completion-list
              (message "候補: %s" (string-join completion-list ", "))
            (message "候補なし")))
      (message "シンボルが見つかりません"))))

この関数ではカーソル位置からシンボルを取得し、それに基づいて候補を表示する。これがあればコーディング中も迷わず進められるぜ。

5. Emacsと共に生きるコミュニティ

Emacsユーザーとして活動している中で、多くの仲間と出会った。

彼らとの情報交換や共同開発は刺激的で、新しいアイデアが次々と生まれてくる。この循環こそが俺の成長につながっていると実感しているんだ。

最近では、自分が開発したパッケージGitHubで公開し、フィードバックを受け取ってさらなる改善点を見つけたりもしている。

このフィードバックループがあるからこそ、自分自身進化し続けられるんだ。

結論Emacsこそ俺の人生

今やEmacsは単なるツールじゃなくて、俺自身の一部になってる。

この深淵世界で探求し続けることで、新たな発見や挑戦が待っている。

これからEmacsユーザーとして、自分だけのユニーク環境を追求し続けていくつもりだぜ!

2024-05-06

[] 2024-05-06

今日入院している祖母に会いに行く日だ。入院前はもう呆けて風呂も入らないぐらいひどい状態だったが、入院してからちゃんとしているらしい。

それはそうと、lisppython環境を構築する話だが、結局オートコンプリートはうざいし、使う機能といったらautopep8とisortぐらいなので、以下を.emacsに組み込んだ。

(defun python-autopep8-and-isort ()
  "Run autopep8 and isort on current Python buffer."
  (interactive)
  (when (eq major-mode 'python-mode)
    (shell-command-on-region (point-min) (point-max)
                             "autopep8 - | isort -" nil t)))

(with-eval-after-load 'python
  (define-key python-mode-map (kbd "C-c C-r") 'python-autopep8-and-isort))

.emacsファイルには他にも様々な設定を付与したが、ここではコードを書ききれない。

さてそういうわけで週末コーディング趣味としてちゃん機能することはわかったが、毎週作るとなると、いくつも何かを作るよりは一つのタフなものを作りたいと思うわけである

それで、最有力候補は「Elasticsearchのようなものpython実装する」という話がある。

Elasticsearchが徹底された設定外部化によってjsonを多用するのだが、これがあまり柔軟性がないので、コードを直にいじれるようにしたいと思ったためである

例えば自作日本語トーカナイザを組み込みたいときElasticsearchプラグインJavaで書かなければならない。私はJavaが嫌いであり、プラグインを「インストールする」という手順も冗長に感じる。

それよりはpythonで作られた検索システムに、適当トーカナイズ関数実装して呼び出すことができればかなり柔軟であるように思うわけである

難しい点があるとすれば、大規模分散システムへの対応で、金をかけなければそういうシステムテストすることができない。

できるだけ金をかけずに趣味をやるというのがモットーなので、これではまずいわけである

まあ何事も困難というものはある。まずは手を動かすことが重要だ。Linus Torvaldsも"Talk is cheap, show me the code"と言っているではないか

2020-09-22

anond:20200921040234

さらここで何かを書いても,あまり助けにならないかもしれないけれど,もしまだ入門する気があったら気に留めておいてほしい.

パッケージの導入方法がわからない

package, use-package, leafどれでも構わない.ただ混在させるとエラーwarningを出したりするので,統一をしたほうがいいとは思う.新しいとか古いとかはこの際気にしなくていい.最近Emacs標準でpackage.elがついているので,めんどくさければ全部packageを使えば問題ない.

こういうのは,Emacsを使っているうちに「自分.emacsをいじるのを結構楽しんでいるな」と思ったときに,新しいのやスマート方法を調べれば十分だ.


簡単操作をするのにもいちいち調べないと行けないのが面倒

これは入門時は仕方ない.ただ後述するhydraを使ってくれ.そうすれば一度調べたものをもう一度調べることがなくなると思う.

とにかくキーバインドを覚えるのが面倒

hydraを使おう.

https://github.com/abo-abo/hydra

hydraってのは,複雑なキーバインドを覚えられない,覚えたくない場合に入れるパッケージだ.Emacsだと,導入したパッケージデフォルトで設定されているキーバインドと,自分カスタマイズしたキーバインド,両方を覚えておく必要がある.けど,そんなの覚えてられるのは一部だけなので,よく使うコマンド一覧を自分で設定できて,それを表示してくれるのがhydraだ.

表示するコマンド一覧を自分で設定するので,↑で調べたときに調べたコマンドを全部hydraの設定に書いておくといい.また,そのときキーバインドも判明したのであれば,hydraのコマンド説明部分にキーバインドも書いておくといい.

使ってる人が居ないので情報もない

これはすまん.使ってる人は実はそこまで少数ではないんじゃないかなと思っているけど,確かに日本語発信している情報は少ない.あと,たいていのパッケージgithub等に公開されていて,玄人達は,英語が読める or そもそもソースlispで書いてあるんだから読めばいいじゃん,という人たちが多い気はする.確かに私も日本語情報特に少ないと感じている.

Emacs-jpbeginners-helpはあんまりbeginnerじゃない質問がされているけれど,気にせず初心者質問をしても大丈夫場所なので,遠慮なく聞いてくれ.回答がわからなければ,「何言ってるのか全然わからん」と言ってくれ.

Windowsしか使わない人に冷たい

そういえば私もWindowsEmacsを使ったことがないので何もわからない…….でも,そこまで困っているならきっとWindows Emacsユーザ全員が困っているはずなので,Emacs-jpで聞いてみたらいいかもしれない.もしくはWindowsユーザチャンネル作ってみたらいいかもしれない.すまん,これについては助けになれない.






キーバインドが覚えられないのは,実はあなただけじゃなくてみんな同じだったからhydraなんてものが出てきたし,日本語情報が少ないのは事実だ.だからまり卑下しないでくれ.偉そうに書いたけど,私も日本語情報が少なくて結構からないことは多かったりする.READMEに書いてあるとおりにセットアップしてもエラーが出たりすることは結構多い.だから,こういう意見に耳を傾けて,Emacsコミュニティ人類に優しくなってほしいと願っている.

2012-03-21

よく見るgentoo女の特徴

元ネタ http://anond.hatelabo.jp/20120321162723

    ( http://anond.pha11.info/archives/9491 )

2009-02-02

http://anond.hatelabo.jp/20090202222941

はい。

Emacs以外のアプリをいじるときに間違ってEmacsキーバインドが出て舌打ちするようになれば一人前のEmacsキーバインダーです。

(一人前のEmacs使いは.emacsをガシガシ編集するからまだまだこの時点でEmacs初心者脱却直前)

 

なおこの病気は罹患すると不意に使わなければならなくなったVimを激しく憎んでしまうため注意が必要です。

2008-11-07

Haskellerと付き合い始めたのだが

http://anond.hatelabo.jp/20081105135432


彼女ができた。なんとHaskellerだ。


8月に参加したLLイベントで知り合い、10月から付き合い始めた。なんでLLイベントにHaskellerが…

これまで5人くらいのプログラマと付き合ったことがあるけれど、一般的なプログラマと比較して

といった点が目立つ。


見た目はLisperを少し丸くしたようなかわいらしさがあるのだけれど、要するに中身はPrologだ。

初めは戸惑いもあったが、案外こういうプログラマとつきあうのは楽で楽しいと分かってきた。


コードは深い問題もFizzBuzzのような軽い問題も内容を伴って書ける。

いろいろメタプログラミング・アロー記法ユニコード演算子などを試そうとするなど好奇心が強い。

純粋関数型言語も習得しているというのに論理系の言語も習得しようと勉強していて向上心の強さがある。


反面、入出力のコード論理的・合理的なのかな…と思いきや、

IOモナドコントロールできない自分に「おかしいな、普段はこんなはずじゃないのに///」と恥ずかしがる。


Haskeller、はっきり言ってオススメです。

問題はどうやって知り合うかだけれど、職場(あるのか?)という戦闘モードの時に誘うのではなく、.emacsなどを書いているオフタイムが狙い目としか。

初めの一歩が難しいだけで、後は一般的な女の子よりも付き合いは簡単かも。

だって普段Makefileに書いている論理と同じでいいんだから。

2008-10-18

http://anond.hatelabo.jp/20081018072817 の続きだよ

これでおしまいだよ

elisp

sangels.el
(require 'cl)				; for cl-seq

(defvar sangels-movies-dir nil)
(defvar sangels-player "c:/Program Files/GRETECH/GomPlayer/GOM.exe")
(defvar sangels-sort-by 'sangels-sort-by-rate)
(defvar sangels-rate-file "~/.emacs.d/.sangels/rate")
(defvar sangels-buffer "*sangels*")
(defvar sangels-thumbnail "00_thumbnail.jpg")
(defvar sangels-m3u "00_movies.m3u")
(defface sangels-name '((t (:family "fixed" :weight bold :height 3.0)))
  "")
(defface sangels-rate '((t (:family "fixed" :weight bold :height 1.5)))
  "")
(defvar sangels-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "n" 'next-line)
    (define-key map "p" 'previous-line)
    (define-key map (kbd "RET") 'sangels-select)
    (define-key map (kbd "SPC") 'sangels-select)
    (define-key map "q" 'sangels-quit)
    (define-key map "+" 'sangels-rate-plus)
    (define-key map "-" 'sangels-rate-minus)
    map))
(defvar sangels-mode-hook nil)
(defvar sangels-highlight-overlay nil)
(defvar sangels-rate-alist nil)

(defconst sangels-rate-max 6)

(defun sangels-insert-movies ()
  (save-excursion
    (let* ((inhibit-read-only t)
           (files (remove-if-not
                   (lambda (x)
                     (and (not (member (file-name-nondirectory x) '("." "..")))
                          (file-directory-p x)
                          (member sangels-thumbnail (directory-files x))))
                   (directory-files sangels-movies-dir t)))
           (ids (mapcar 'file-name-nondirectory files)))
      (erase-buffer)
      (setq ids (sangels-sort-ids ids))
      (dolist (id ids)
        (let ((file (expand-file-name id sangels-movies-dir))
              (pos (point)))
          (insert-image-file (expand-file-name sangels-thumbnail file))
          (end-of-line)
          (insert (propertize (format "%-15s " id)
                              'face 'sangels-name))
          (sangels-insert-rate id)
          (insert "\n")
          (put-text-property pos (point) 'sangels-id id))))))

(defun sangels-sort-by-name (a b)
  (string< a b))

(defun sangels-sort-by-rate (a b)
  (or (> (sangels-rate a) (sangels-rate b))
      (sangels-sort-by-name a b)))

(defun sangels-sort-ids (ids)
  (sort ids
        (or sangels-sort-by
            'sangels-sort-by-name)))
(defun sangels-insert-rate (id)
  (let ((rate (sangels-rate id)))
    (insert (propertize (concat
                         (make-string rate ?★)
                         (make-string (- sangels-rate-max rate) ?☆))
                        'sangels-rate t
                        'face 'sangels-rate))))

(defun sangels-current-id ()
  (get-text-property (point) 'sangels-id))

(defun sangels-play-movie (movie)
  (let ((explicit-shell-file-name "cmdproxy")
        (shell-file-name "cmdproxy"))
    (apply
     'call-process-shell-command
     "start" nil "*tmp*" nil
     (mapcar (lambda (x) (concat "\"" x "\""))
             (list sangels-player
                   (unix-to-dos-filename movie))))))

(defun sangels-select ()
  (interactive)
  (let ((id (sangels-current-id)))
    (when id
      (sangels-play-movie (expand-file-name
                           sangels-m3u
                           (expand-file-name id sangels-movies-dir))))))

(defun sangels-quit ()
  (interactive)
  (kill-buffer sangels-buffer))

(defun sangels-rate (id)
  (or (cdr (assoc id sangels-rate-alist)) (/ sangels-rate-max 2)))

(defun sangels-rate-save ()
  (interactive)
  (let ((dir (file-name-directory sangels-rate-file)))
    (unless (file-exists-p dir)
      (make-directory dir t)))
  (with-temp-file sangels-rate-file
    (insert (pp-to-string sangels-rate-alist))))

(defun sangels-rate-load ()
  (interactive)
  (when (file-exists-p sangels-rate-file)
    (with-temp-buffer
      (insert-file-contents sangels-rate-file)
      (goto-char (point-min))
      (setq sangels-rate-alist (read (current-buffer))))))

(defun sangels-rate-plus (&amp;optional n)
  (interactive "p")
  (setq n (or n 1))
  (let* ((id (sangels-current-id))
         (cell (assoc id sangels-rate-alist)))
    (unless cell
      (setq cell (cons id (sangels-rate id)))
      (setq sangels-rate-alist (cons cell sangels-rate-alist)))
    (setcdr cell (+ (cdr cell) n))
    (save-excursion
      (let ((inhibit-read-only t))
        (beginning-of-line)
        (goto-char (next-single-property-change (point) 'sangels-rate))
        (delete-region (point)
                       (next-single-property-change (point) 'sangels-rate))
        (sangels-insert-rate id)))
    (sangels-rate-save)))

(defun sangels-rate-minus (&amp;optional n)
  (interactive "p")
  (setq n (or n -1))
  (sangels-rate-plus (- n)))

(defun sangels-post-command-hook ()
  (save-excursion
    (move-overlay
     sangels-highlight-overlay
     (progn
       (move-beginning-of-line 1)
       (point))
     (progn
       (move-end-of-line 1)
       (forward-line)
       (point))
     (current-buffer))))

(defun sangels-mode ()
  (interactive)
  (kill-all-local-variables)
  (use-local-map sangels-mode-map)
  (setq sangels-highlight-overlay (make-overlay 0 0))
  (overlay-put sangels-highlight-overlay 'face 'highlight)
  (overlay-put sangels-highlight-overlay 'evaporate t)
  (make-local-variable 'post-command-hook)
  (add-hook 'post-command-hook 'sangels-post-command-hook nil t)
  (setq major-mode 'sangels-mode)
  (setq mode-name "Sangels")
  (run-mode-hooks 'sangels-mode-hook)
  (set-buffer-modified-p nil)
  (setq buffer-read-only t))

(defun sangels (&amp;optional arg)
  (interactive "P")
  (when (or arg (not sangels-movies-dir))
    (setq sangels-movies-dir (read-directory-name "movies dir: ")))
  (sangels-rate-load)
  (switch-to-buffer (get-buffer-create sangels-buffer))
  (sangels-insert-movies)
  (sangels-mode))

(provide 'sangels)

2007-08-03

http://anond.hatelabo.jp/20070803192425

あるある。プラットフォーム依存な開発をやってて、普通秀丸とか Vim とか Emacs とか WzEditor とか Eclipse とかが混在した状態で開発してる時に、Emacs ユーザーがスペースとタブの混在インデントをやってたのを見た時、もう、ぼろくそにおきおろしたくなるのを我慢して「他の人が困るから .emacs とかにこれこれこうこう書くとかしてプロジェクトファイルを置いてるディレクトリ配下のファイル編集する場合だけでいいから周囲に合わせられるように設定してね」って教えてあげたことがある。かなしかったよ。

2007-07-22

ファッションギーク

  • CUIが好き。しかし実際の作業は全てマウスを使ってGUIで行う。
  • Windowsが嫌い。しかし嫌いになる理由が特にあるわけではない。
  • Linuxが好き。しかし本格的に使ったことはなく、VMware上にインストールするだけで満足している。
  • Macが好き。しかし好きな理由が特にあるわけではない。
  • emacsが好き。しかし本格的に使ったことはなく、他人の.emacsコピペしてカスタマイズするだけで満足している。
  • vimが好き。しかし独特の操作体系に慣れることができず、死ぬほど使いにくいと思っているが口には出さない。
  • Rubyが好き。しかし好きな理由が「他の人が良いって言っているから」。
  • ぬるいやつらが嫌い。しかし自らがぬるい人間であることは全力で見逃していて、上記のようなことを書き連ね悦に浸る。
ログイン ユーザー登録
ようこそ ゲスト さん