2014年1月23日木曜日

[Sublime Text 3] LaTeXing を消した後にエラーが出る時の対処法


Sublime Text 3 で LaTeXing という TeX 用のパッケージを使っていたのですが、「ライセンスを購入してね☆」とうるさかったので、LaTeX Tools に乗り換えました。

Remove Package から LaTeXing を削除した後、Sublime Text 3 を再起動すると以下のようなアラートが表示されました。

Error loading syntax file "Packages/LaTeXing/support/LaTeX.tmLanguage":
Unable to open Packages/LaTeXing/support/LaTeX.tmLanguage

何度再起動しても同じアラートが発生するので原因を調べたところ、どうやら、LaTeXing を使っていた時のファイルをタブで開きっぱなしなのがいけないらしい。

$ cd ~/Library/Application Support/Sublime Text 3/Local
$ cat Session.sublime_session |grep -i latex
"syntax": "Packages/LaTeX/LaTeX.tmLanguage"
"syntax": "Packages/LaTeXing/support/LaTeX.tmLanguage"

こんな感じで、セッションに LaTeXing で 文法チェックした履歴が残っていたためです。


対処法は簡単。

・編集時に LaTeXing を使っていた TeX ファイルのタブを閉じて、再度開き直す。
・もしくは、Sublime Text 右下のファイルの種類を変更するところから、再度 LaTeX > LaTeX を選択する(下図参照)。

こうすれば、アラートは表示されなくなりました。

2014年1月12日日曜日

[Blogger] SyntaxHighlighterの表示をしましまにする

SyntaxHighlighter をデフォルトのまま使っていたのですが、白背景だとソースコードが目立ちにくいのでcssを修正しました。

BloggerのテンプレートのHTMLのhead内に追記。

<style type='text/css'>
    /* 外枠を追加 */
    .syntaxhighlighter {
        border: 1px solid #aaa;
        border-radius: 3px;
    }
    /* 偶数行目の背景色を変更 */
    .syntaxhighlighter .line.alt2 {
        background-color: #f8f8f8 !important;
    }
    td.gutter .line.alt2 {
        background-color:#e6e5e1 !important;
    }
</style>

参考ページ
SyntaxHighlighterのデザインをカスタマイズ変更する
ソースコードを美しく公開する方法 - 「SyntaxHighlighter」の使い方

2014年1月11日土曜日

[SublimeText3] Sublime Text 3にSublimeLinterを入れてPythonを設定する


タイトルの通り、Sublime Text 3にSublime Linterを追加して、さらにPython用の設定(pep8, pep257)をします。




Package Controlを導入

Package Controlのページの説明の通りです。

Sublime Textを起動後、Ctrl + ` もしくは、ツールバーの Views > Show Console からコンソールを起動します。

以下の内容をコピー&ペーストして、Enterを押せば完了。

import urllib.request,os,hashlib; h = '7183a2d3e96f11eeadd761d777e62404e330c659d4bb41d3bdf022e94cab3cd0'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)


SubLimeLinterを追加

Ctrl + Shift + PでCommand Paletteを開いて、"ins"と入力、Install Packageを選択します。



"sublimelinter"と入力し、SublimeLinterを選択するとインストールされます。



少し分かりにくいですが、インストール中はステータスバーに [ = ] が表示されます。




同様に、SublimeLinter-pep8, SublimeLinter-pep257もインストールします。




pep8, pep257のインストール

pipを使ってpep8, pep257をインストールします。

$ sudo pip3.3 install pep8 もしくは $ sudo pip install pep8

$ sudo pip install pep257


SublimeLinterの設定

最後にSublime Textを再起動すればすぐに利用可能ですが、このままでは少しうるさいので設定を変更します。
PEP8に完全に則ってコーディングをする場合は設定は不要です。



こんな感じで、ソースコードを読みやすくするための空白にもエラーが出てしまいます。


Package Settings > SublimeLinter > Settings User を選択、編集します。



まず、注意・警告部分を「囲む」のではなく、「下に波線を表示」にします。
// "mark_style": "outline", の行を削除して以下の行を挿入
"mark_style": "squiggly underline",

その他波線以外の形式は、画像付きでこちらに掲載されています


続いて、コードを読みやすくするための空白を許すように変更します。

// "ignore"内にカンマ区切りで記入
"pep8": {
    "ignore": "E203,E221,E241,E272",
}

"ignore"内に、無視するルール名をカンマ区切りで書いていきます。
今回は、以下の4つを設定しました。
E203 : コロンの前の空白禁止
E221 : イコールなどの演算子の前に複数の空白を入れてはいけない
E241 : カンマの後に複数の空白を入れてはいけない
E272 : キーワードの前に複数の空白を入れてはいけない

その他のルールは、pep8のドキュメントに書いてありますので、そちらを参照して下さい。



うん、そんなにうるさくエラーを吐かなくなりました。
あんまり厳しくルールを縛られると、コーディングが億劫になっちゃいますからね笑

2014年1月9日木曜日

[JavaScript] 数字を使わずに数字を表現する


JavaScriptで数値リテラルを使わずに整数を表現する方法を考えてみました。

普段使うことは絶対ありませんが、縛りありのプログラミングコンテストなんかやるときには面白いかもしれない(と、codeiqの問題を解きながら思いました)。


文字列の長さを使う

一番ベタな方法。
>>> "".length
0
>>> "a".length
1
>>> "aaa".length
3
>>> Math.pow("aaa".length,"aa".length);
9

Mathの定数を使う

ちょっとずるい気もするけど、工夫次第で色々な数字を作れる。
>>> parseInt(Math.E)
2
>>> Math.ceil(Math.PI)
4
>>> Math.floor(Math.PI*Math.E-Math.LOG2E)
7

論理演算を使う

文字リテラルもMathも使わない場合は結構大変。
// trueは1
>>> true+true
2

Dateを使う

タイミング依存の最終手段。
>>> now = new Date();
>>> now.getFullYear();
2014
// 各桁の和を求める
>>> String(now.getFullYear()).split("").reduce(function(x,y){return Number(x)+Number(y);})
7

2014年1月5日日曜日

[Python] Twitterの画像を一括でダウンロードするスクリプト


Twitterにアップロードした(された)画像を一括でダウンロードできるスクリプトを作りました。

Twitterのページの、画像/動画部分に表示されている画像をダウンロードできます。ただし、外部サイトにアップロードされた画像のダウンロードには対応していません。

動作には、Twython(Python用のTwitterライブラリ)が必要です。


(準備)twythonのインストール


$ pip install twython


画像の一括ダウンロード


Twitterのアプリケーションキーを持っていない場合は、My applications | Twitter Developersから発行する必要があります。アプリケーション作成後、My applicationsからアプリケーションを選択し、OAuth toolタブからConsumer Key等を確認できます。

TwitterAPIの利用回数制限を超えないように適当にスリープを挟んでいますが、ダウンロードする数が少ない場合は必要ないかもしれません。また、既に同一名の画像がダウンロードされている場合には、再ダウンロードを行わないようになっています。


以下、ダウンロード用のスクリプトです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import time
import urllib2
from twython import Twython

u"""
ツイッターで投稿された画像を一括でダウンロードする
"""

# 画像を保存するディレクトリ(予め作成しておく)
# 各ユーザの画像は、./images/screen_name/ 内に保存される
IMAGES_DIR = './images/'

# Twitter 認証関係 https://dev.twitter.com/apps
# Consumer key
CK='Consumer keyをここに記入'
# Consumer secret
CS='Consumer secretをここに記入'
# Access token
ATK='Access tokenをここに記入'
# Access token secret
ATS='Access token secretをここに記入'

# 取得するツイート数の最大値の設定(以下の2つの値の積)
NUM_PAGES       = 5         # 取得するページ数
TWEET_PER_PAGE  = 200       # 1ページあたりのツイート数(最大200)

# 画像をダウンロードするユーザのスクリーン名を1行に1人ずつ記入する(@の有無は問わない)
SCREEN_NAMES = '''
screen_name_1
screen_name_2
@screen_name_3
'''


class TwitterImageDownloader(object):
    u"""Twitterから画像をダウンロードする"""
    def __init__(self):
        super(TwitterImageDownloader, self).__init__()
        self.twitter =Twython(app_key=CK, app_secret=CS, oauth_token=ATK, oauth_token_secret=ATS)

    def read_ids(self):
        ids_all = [line.replace('@', '') for line in SCREEN_NAMES.splitlines() if line]
        ids = sorted(list(set(ids_all)))
        return ids
    
    def get_timeline(self, screen_name):
        max_id = ''
        url_list = []
        for i in xrange(NUM_PAGES):
            try:
                print 'getting timeline : @', screen_name, (i+1), 'page'
                tw_result = (self.twitter.get_user_timeline(screen_name=screen_name, count=TWEET_PER_PAGE, max_id=max_id)
                    if max_id else self.twitter.get_user_timeline(screen_name=screen_name, count=TWEET_PER_PAGE))
                time.sleep(5)
            except Exception as e:
                print "timeline get error ", e
                break
            else:
                for result in tw_result:
                    if 'media' in result['entities']:
                        media = result['entities']['media']
                        for url in media:
                            url_list.append(url['media_url'])
                    max_id = result['id']
            if len(tw_result) < TWEET_PER_PAGE:
                break
        return url_list

    def create_folder(self, save_dir):
        try:
            os.mkdir(save_dir)
        except Exception as e:
            print 'cannot make dir', e
        file_list = os.listdir(save_dir)
        return file_list

    def get_file(self, url, file_list, save_dir):
        file_name = url[url.rfind('/')+1:]
        url_large = '%s:large'%(url)
        if not file_name in file_list:
            save_path = os.path.join(save_dir, file_name)
            try:
                print "download", url_large
                url_req = urllib2.urlopen(url_large)
            except Exception as e:
                print "url open error", url_large, e
            else:
                print "saving", save_path
                img_read = url_req.read()
                img = open(save_path, 'wb')
                img.write(img_read)
                img.close()
                time.sleep(1)
        else:
            print "file already exists", file_name

    def download(self):
        screen_name_list = self.read_ids()
        num_users = len(screen_name_list)
        for i, screen_name in enumerate(screen_name_list):
            save_dir  = os.path.join(IMAGES_DIR, screen_name)
            file_list = self.create_folder(save_dir)

            url_list = self.get_timeline(screen_name)
            num_urls = len(url_list)
            for j, url in enumerate(url_list):
                self.get_file(url, file_list, save_dir)
                print "%d / %d users, %d / %d pictures"%((i+1), num_users, (j+1), num_urls)

def main():
    tw = TwitterImageDownloader()
    tw.download()

if __name__ == '__main__':
    main()

2014年1月2日木曜日

[django] 既存のプロジェクトにsouthを追加する方法



1.southのインストール


$ pip install south


2.settings.pyに追記

settings.py の INSTALLED_APPS に'south'を追記します。

$ vi settings.py
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'アプリ名1',
    'アプリ名2',

    # southを追加
    'south',
)


3.既存のアプリをsouthに追加

既にデータベース上にテーブルが作成されている各アプリについて、以下のコマンドを実行します。

$ python manage.py schemamigration アプリ名 --init
$ python manage.py migrate アプリ名 --fake


--fake を付けるのを忘れると、southは新たにテーブルを作成しようとし、エラーが返ってきます。


(おまけ) 初期化完了後、モデルの変更時

以下のコマンドを実行すると、モデルの変更をデータベースに反映できます。
$ python manage.py schemamigration アプリ名 --auto
$ python manage.py migrate アプリ名


なお、既存のデータに対してdefault値などが設定されていない列を追加する場合は、初期値としてどのような値を入力するかを聞いてくれます。
この際、datetime.datetime.now()等のpythonの式を代入することもできるので便利ですね。



2014年1月1日水曜日

[Webサイト] オタク用語の和英辞書サイトを作った


新年あけましておめでとうございます。

さて、ネット用語やゲーム用語、新しい略語など、使う人が限られる用語ってあまり辞書には載りませんよね。
自分はよく海外サイトの掲示板を見るのですが、そこで使われている略語やスラングが分からなくて、意味を理解するのに苦労することもしばしば。

そこで、そういったちょっとマニアックな用語や文例を集めた和英辞書を作りたいと思い、こんなサイトを立ち上げました。



Otaku Slang Dictionary | オタク用語辞書



スマホから見ると、こんな感じ。

内容としては、ネットスラングやアニメ・ゲーム用語、同人用語や音楽用語など、ネット上の辞書でもあまり扱われないような、マニアックな単語とその用例を集めています(現在進行形)。


特徴



編集が簡単

Wikiのように誰もが追加・編集可能であることが特徴で、単語や用例を簡単に編集できるようにしています。
また、編集を行わなくても気軽に内容の追加依頼や間違いの指摘が可能になるよう、各単語のページにコメント欄を設け、簡単な掲示板としてフォーラムを作りました。


誰でも編集が可能です。


単語を探しやすい

ABC順の辞書的な並びだけではなく、カテゴリ別の表示や、検索フォームを設けることで、目的の単語を容易に探せるようにしました。


カテゴリ別表示と検索フォーム。


見やすい

最近はPCだけでなく、スマートフォンやタブレットを使ってアクセスする人も多いと思い、ページの作成にjQuery Mobileを使っています。


日本語・英語対応

主要な説明や見出しには日本語と英語を併記しています。日本人の方だけでなく、日本のオタク文化を愛する外国人の方にも使ってもらえたら嬉しいなーと思っています。



まだ単語も数十個しか登録されていませんが、こんな感じで頑張って辞書を作っていきたいと思います。
手伝ってくれるという方は、是非どんどん編集してください!

Otaku Slang Dictionary | オタク用語辞書はこちら