日々是好日

プログラミングについてのあれこれ、ムダ知識など

技術書典6のサンプル集

主な内容

環境構築の章サンプル

drive.google.com

コマンド系拡張機能の章サンプル

drive.google.com

シンタックスハイライト開発の章サンプル

drive.google.com


よろしくお願いしますです。

私の Re:VIEW 3.0 対応(参考)

Re:VIEW 3.0 がリリースされ、 kmuto さんにもいろいろとご教授いただいたので対応まとめ。ご参考まで。

  1. 既存の Re:VIEW 2 系文書の 3 系移行
  2. 新規の Re:VIEW 3 系文書の生成(ReVIEW-Template ベース)

どちらも必要なことはだいたい同じ。
なお細かい配置や装飾等は全然わからないので、問題があったら kmuto さんに Issue 投げてくだせい。 とても優しく対応していただけました。

  • 環境
  • 何が必要か
    • sty ファイル, config.yml の更新
    • layouts フォルダの中身を空にする
    • カスタム大扉の作成
    • 打消し線の設定
  • P.S.
  • 追記(2019-02-19)
続きを読む

二分探索を VBA で実装してみた

「アッ二分探索木(バイナリサーチ)実装してみたい!再帰的に!!」

ってふと思い立ったので、 2 日かけて書いてみた。我ながら変態かよ。

まともに再帰的なコード書いたのは初めてくらい。 どう実装に落とし込むのかの理解がムズカシカッタ。。。

一応条件。

  • 諸事情により VBA
  • 使うセルはWorksheets("Sheet1")の A列 のみ
  • A列 に昇順で適当な値を入れておく(リストの代わり)
  • 出力値は、探索値が入ってるセルの行番号(A50のセルで見つければ50が出力)
  • 値が見つからなければ-1を出力
Option Explicit

Dim sh As Worksheet
Dim target As Integer

Sub startSearch()

    target = 'ここに探索する値をベタ打ち'

    Set sh = ThisWorkbook.Worksheets("Sheet1")

    Dim result As Integer
    Dim maxRow As Integer
    maxRow = sh.Cells(Rows.Count, 1).End(xlUp).Row
    result = binarySearch(getNextPoint(1, maxRow), 1, maxRow)
    Debug.Print ("row: " & result)

    Set sh = Nothing

End Sub

Function binarySearch(pointer As Integer, imin As Integer, imax As Integer)

    If imax - imin = 1 Then
        binarySearch = -1
    ElseIf sh.Cells(pointer, 1).Value < target Then
        binarySearch = binarySearch(getNextPoint(pointer, imax), pointer, imax)
    ElseIf sh.Cells(pointer, 1).Value > target Then
        binarySearch = binarySearch(getNextPoint(imin, pointer), imin, pointer)
    Else
        binarySearch = pointer
    End If

End Function

Function getNextPoint(imin As Integer, imax As Integer) As Integer

    Debug.Print ("imin: " & imin & ", imax: " & imax)
    getNextPoint = imin + WorksheetFunction.RoundDown((imax - imin) / 2, 0)

End Function

取り急ぎ投稿したくなったので、後で肉付けする←←

はてな API を叩いて投稿

はてなブログへの記事投稿部分の実装。この記事も VSCode 拡張機能からの投稿です。

HatenaBlogUtil

Post するデータはまるっとoauth.postcontentに入れてしまえば OK らしい。

export default class HatenaBlogUtil{
    postMember() {
        ...
        const folders = vscode.workspace.workspaceFolders;
        if (folders !== undefined){
            //Macはfolders[0].uri.path
            const root = folders[0].uri.fsPath; 
            const converter = Converter.getInstance();
            this.oauthPOST(this.atomUri + "/entry", converter.createPostData(root), (err, result, responce) => {
                console.log(err);
                console.log(result);
            });
        }
    }

    private oauthPOST(uri: string, content: any, callback: OAuth.dataCallback) {
        if (this.authorizer.existAccessToken()){
            const oauth = this.authorizer.getOAuth();
            oauth.post(uri,
                'Access Token',
                'Access Token Secret',
                content,
                'text/x-markdown',
                callback
                );
        }
    }
}

Converter

Converterはとりあえずシングルトンで実装。 readFileSyncは非同期版のreadFile使いたいけど、軽度のコールバック地獄になりそうなので思案中。

export default class Converter{
    ...
    createPostData(root: string, draft?: boolean) {
        const prefs = vscode.workspace.getConfiguration('UserPreferences');
        const id = prefs.get<string | undefined>('id');
        const _content = fs.readFileSync(root + "\\content.md", {encoding: 'utf-8'});
        const content = this.escapeHtml(_content);
        const _config = fs.readFileSync(root + "\\config.json", {encoding: 'utf-8'});
        const config = JSON.parse(_config);
        const useDraft = draft? 'yes' : 'no';

        const data =
            '<?xml version="1.0" encoding="utf-8"?>' +
            '<entry xmlns="http://www.w3.org/2005/Atom" ' +
            'xmlns:app="http://www.w3.org/2007/app">' +
            `<title>${config.title}</title>` +
            `<author><name>${id}</name></author>` +
            `<content type="text/x-markdown">${content}</content>` +
            this.createCategoryTerms(config) +
            '<app:control>' +
            `<app:draft>${useDraft}</app:draft>` + 
            '</app:control>' +
            '</entry>';
        
        console.log(data);
        return data;
    }

    private createCategoryTerms(config: any) {
        const category = config.category;
        let terms: string = "";
        category.forEach((element: string) => {
            terms += (`<category term="${element}" />`);
        });

        return terms;
    }

    private escapeHtml (content: string) {
        const replaceMap: {[key: string]: string} = {
            "&": '&amp;',
            "'": '&#x27;',
            '`': '&#x60;',
            '"': '&quot;',
            '<': '&lt;',
            '>': '&gt;'
        };
        
        return content.replace(/[&'`"<>]/g, (match) => {
          return replaceMap[match];
        });
    }
}

content.md

はてな Markdown で書くだけ。

config.json

{
    "title": "はてな API を叩いて投稿",
    "category": [
        "VSCode",
        "VSCode拡張機能開発",
        "TypeScript",
        "プログラミング"
    ]
}

画像はまだ使えないけどショートカットとかハイライトとか使えるのでめっちゃ書きやすい!!ユーザスニペットも設定してるのでやばい!!(自画自賛

参考

Html エンコードについて。

qiita.com