C/C++」タグアーカイブ

Gedit gcc

Gedit の外部ツールは便利だが自分で設定したショートカットキーを忘れる。
簡単なキーに割付けたくてもできないことも多いし。
特に C ビルドで GLib や Nemiver の利用を振り分けしたい場合とか。

Nemiver | PaePoi

本格的に作るものなら当然 Makefile を用意するので問題ない。
けれどチビッと試したいコードのためにそんな面倒したくないですよ。
プログラミング関連は全部 F5 キーだけでまかなえないものか。

そうだ、’GLib.h’ という文字列が含まれているかどうかで振り分けできないか?
ものは試しだ、こんなツールを作ってみた。

#!/bin/sh
PYTHON="text/x-python"
GJS="application/javascript"
HTML="text/html"
BASH="application/x-shellscript"
VALA="text/x-vala"
CSRC="text/x-csrc"
echo @MIMEtype $GEDIT_CURRENT_DOCUMENT_TYPE
if [ $GEDIT_CURRENT_DOCUMENT_TYPE = $PYTHON ]; then
    python3 $GEDIT_CURRENT_DOCUMENT_PATH
elif [ $GEDIT_CURRENT_DOCUMENT_TYPE = $GJS ]; then
    gjs $GEDIT_CURRENT_DOCUMENT_PATH
elif [ $GEDIT_CURRENT_DOCUMENT_TYPE = $HTML ]; then
    google-chrome $GEDIT_CURRENT_DOCUMENT_PATH
elif [ $GEDIT_CURRENT_DOCUMENT_TYPE = $BASH ]; then
    sh $GEDIT_CURRENT_DOCUMENT_PATH
elif [ $GEDIT_CURRENT_DOCUMENT_TYPE = $VALA ]; then
    vala $GEDIT_CURRENT_DOCUMENT_PATH
elif [ $GEDIT_CURRENT_DOCUMENT_TYPE = $CSRC ]; then
    src=`cat $GEDIT_CURRENT_DOCUMENT_PATH`
    case $src in
        *gtk.h*)
            echo "Gtk Build"
            gcc $GEDIT_CURRENT_DOCUMENT_PATH `pkg-config --cflags --libs gtk+-3.0` ;;
        *glib.h*)
            echo "GLib Build"
            gcc $GEDIT_CURRENT_DOCUMENT_PATH `pkg-config --cflags --libs glib-2.0` ;;
        *)
            echo "Gcc Build"
            gcc $GEDIT_CURRENT_DOCUMENT_PATH ;;
    esac
else
    echo Non Support File
fi

全部読み込んで case 文にしたのは inclide が一行目とは限らないので。
ぶっちゃけ効率ガン無視だがチョコッとビルド用途なのでいいよね。

ついでに Nemiver 用も

#!/bin/sh

src=`cat $GEDIT_CURRENT_DOCUMENT_PATH`
case $src in
    *gtk.h*)
        echo "Gtk Build"
        gcc -g -o debug $GEDIT_CURRENT_DOCUMENT_PATH `pkg-config --cflags --libs gtk+-3.0`
        if test $? -eq 0; then
            nemiver debug
        fi
        ;;
    *glib.h*)
        echo "GLib Build"
        gcc -g -o debug $GEDIT_CURRENT_DOCUMENT_PATH `pkg-config --cflags --libs glib-2.0`
        if test $? -eq 0; then
            nemiver debug
        fi
        ;;
    *)
        echo "Gcc Build"
        gcc -g -o debug $GEDIT_CURRENT_DOCUMENT_PATH
        if test $? -eq 0; then
            nemiver debug
        fi
        ;;
esac

gedit_tool

これで F5 を押すだけで筆者が使う言語は全部まかなえるぜ。
あと PHP があるけどこれは Apache 経由でしか使わないので。

いや、本当はモードごとに書いたほうがいいのだろうけどね。
ツールが一つで自力振り分けのほうが筆者はメンテが楽なだけ。

Mac x86_64

さて、筆者もついに Mac を手に入れた。
これで Mac 向けアプリの開発、をするかどうか今は解らない。

ところで Mac 向けアプリの C コンパイラは UNIX 系なので gcc である。
困ったことに Xcode 付属品らしい、つまり Xcode を入れる必要がある。

App Store から落とす、って Xcode って 2.57GB もあるんかい!
単なるアプリケーションなのに Fedora iso の二倍って何だよ。
Linux アプリはデカくてもキロバイト単位なので本当にウンザリする。

インストールが終わって即使おうと思ったが gcc が見つからない。
C言語入門 – MacでC言語 – コンパイラ(gcc)のインストール – Xcode – Command Line Tools – Webkaru
こんなページを見つけたけど Yosemite では一度起動すれば自動で入った。

gcc で C/C++ – L’Isola di Niente
OS X はたしか 64bit だったはず。
コンパイラが gcc だから Linux x86_64 と同じ結果になると思う。
上記ページの x86_64 サイズ確認コードを動かしてみる。

以前は sizeof の値を %d にしていたのだが %lu にしろと Warning が出た。
Mac の gcc は Linux より警告レベルを高く設定しているようだ。
ということで %lu 指定に書き換えて普通にビルド、そして実行。

x86_64

やはり Linux x86_64 とまったく同じだね。
日本語を扱う場合は UCS-4 だということに注意しよう。
てか UTF-16 なのは Windows だけなんだが。

しかし /usr/include ディレクトリが存在しないぞ。
スタジオエッチはドコにあるのだ?

stdioh

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include
にあった、なるほど Xcode 必須なわけだ。

まあ Xcode のエディタは思っていたよりシンプルで使えそう。
エディタを探そうと思ったけどコレを使いこなしたほうがよさげ。
というか、なるべくアプリは少なくしたい、デカいのはもう嫌。
私的に必須な逆インデントのショートカットキーもあるので問題ない。

no_modeline

さすがに modeline は使えなかった、惜しい。
ちなみに Gedit は Yosemite では起動すらできなかった。

GtkBuilder

GtkBuilder を入れてみた。
見た目は凄い多機能に見える、どんな感じなんだろう。
ちなみに、コレも dnf コマンドからでないと入らない。

gnome_builder_install

あれ、clang 必須なのかな?
というかこの名前なのに Gtk+ ヘッダは依存関係にはないのかよ。
後で判るけど gcc でよかった、その他必要そうなものも導入しておこう。

早速新規プロジェクトを作ってみよう。
起動すると HDD 内の GPL プロジェクトを自動検索していた。
便利なんだか余計なお世話なのか、大半が参考用なのに。

あらかじめ作業用ディレクトリを作っておいく。
起動したら左上の [New] ボタン、フォルダアイコンのほうをクリック。
先程作ったディレクトリを指定し [Continue] する。

new_proj

configure.ac をプロジェクトファイルとして扱うようだ。
つまり autotools も必須ということみたい。
適当にコードを書いてプロジェクトを保存…

できなかった。

色々試したが autogen.sh 必須。
autotools にて自力で configure.ac を作った後に使うもののようだ。

というか、コイツのビルド機能は autogen.sh を実行するだけ。
そりゃコンパイラはどっちでもいいわ。

一応、autogen.sh は autotools のコマンドをまとめておくスクリプト。
最小限のサンプルを置いておくよ、README のとおりにやってね。
honda-0.0.1.tar.gz

そうそう、Build といっても configure スクリプトを作るまでです。
make 以降は自力。

小物を作って遊ぶには無駄すぎる。
デバッガもない、コレを IDE と言ってもいいのだろうか?
単なるテキストエディタだ。

コード補完や閉括弧自動挿入と初心者大喜びなエディタなのに。
私的に期待外れというかショボすぎて唖然とした。

うーん、今後に期待しとく。

\033[

今日の覚書

【第十二回】エスケープシーケンス(2) – あらほりLinuxメモ

#!/bin/sh

# \033[数値A で戻りたい行数の数値
# \033[0J    でカーソル以降の行を削除

echo いくぞー

for s in いーち にー さーん だぁー!
do
    sleep 1
    printf "\033[1A\033[0J"
    echo $s
done

daa

なるほど、使い道は微妙だけど。
もっと更新してほしいな、忙しいのだろうけど。

1 ページ前の色分けはも含め C や Python からも使えるのね。
しかし cmd.exe はそもそも色分けができないだろ、なんだが。
エスケープシーケンス

Python

#!/usr/bin/env python3

print("\033[32m緑色おおおお");
print("\033[31m赤色おおおお");
# 戻す
print("\033[39m", end='');

C (glib)

#include <glib.h>

int
main (int argc, char* argv[]) {

    g_printf("\033[32m緑色おおおお\n");
    g_printf("\033[31m赤色おおおお\n");
    // 戻す
    g_printf("\033[39m");
    return 0;
}

033

コッチは警告表示で赤で出力とか便利そう。
sh で探して C, Python も使えたので得した気分。

GIOChannel @ End of line

GIOChannel にて scanf でよく使う行末から値を得るように。

#include <glib.h>

int
main (int argc, char* argv[]) {

    GError *error = NULL;
    GIOChannel *channel;
    gchar *text;
    gsize length, terminator_pos;

    g_printf("Input :");

    channel = g_io_channel_unix_new(0);
    g_io_channel_read_line(channel, &text, &length, &terminator_pos, &error);
    g_io_channel_unref(channel);

    text[terminator_pos] = '\0';
    g_printf("output[%s]\n", text);
    g_free(text);

    return 0;
}

giochannel

なんだよコレ、いきなり入力画面になるんだが。
しばらく悩んでやっと手段を見つける。

#include <glib.h>

int
main (int argc, char* argv[]) {

    GError *error = NULL;
    GIOChannel *channel;
    gchar *text;
    gsize length, terminator_pos;

    g_printf("Input\n"); /* Important '\n' */

    channel = g_io_channel_unix_new(0);
    g_io_channel_read_line(channel, &text, &length, &terminator_pos, &error);
    g_io_channel_unref(channel);

    text[terminator_pos] = '\0';
    g_printf("output[%s]\n", text);

    g_free(text);
    return 0;
}

giochannel2

改行するだけだった、いやだから行末から値を得たいのですけど。
GIOChannel では一行単位でしか値を得られないのだろうか。

よくワカラン、ならば入力も GIOChannel にしたらどうだ?
これは上手くいったのでコメントと例外処理を付ける(外国人用)

#include <glib.h>

int
main (int argc, char* argv[]) {

    GError *error = NULL;
    GIOChannel *channel;
    GIOStatus status;
    gchar *text;
    gsize length, terminator_pos;

    for (;;) {

        /* stdout */
        channel = g_io_channel_unix_new(1);
        status = g_io_channel_write_chars(channel, "Exit if string is empty :", -1, NULL, &error);
        if (status == G_IO_STATUS_ERROR) {
            g_warning (error->message);
            g_error_free (error);
            g_io_channel_unref(channel);
            return 1;
        }
        g_io_channel_unref(channel);

        /* stdin */
        channel = g_io_channel_unix_new(0);
        /* Start from the end of the line */
        status = g_io_channel_read_line(channel, &text, &length, &terminator_pos, &error);
        if (status == G_IO_STATUS_ERROR) {
            g_warning (error->message);
            g_error_free (error);
            g_io_channel_unref(channel);
            return 2;
        }
        g_io_channel_unref(channel);

        /* Exit if string is empty */
        if (terminator_pos == 0) {
            g_free(text);
            break;
        }
        /* Remove '\n' */
        text[terminator_pos] = '\0';
        g_printf("[%s]\n", text);

        g_free(text);
    }
    return 0;
}

giochannel3

g_io_channel_write_chars での出力なら当然のごとく行末からに。
g_printf がバッファの行末へ入出力ポインタを seek しないのかな。
いや、g_printf を連続して呼べば追記になるのだからそれは違う。

単純にまったく別のポインタ管理をしているのかも。
もしそうなら下記のようにすれば上書きか挿入かがされるはず。

#include <glib.h>

int
main (int argc, char* argv[]) {

    GIOChannel *channel;

    g_printf("First");
    g_printf("Second");
    channel = g_io_channel_unix_new(1);
    g_io_channel_write_chars(channel, "Third", -1, NULL, NULL);
    g_io_channel_unref(channel);
    return 0;
}

giochannel4

見事に挿入されてしまった、そういうことか。
最初のいきなり入力画面は表示できない二行目に押し出されていたのね。
日本語情報が無いに等しいから自分で見つけるしかないのが辛いNE。

GIOChannel と g_printf は混在させないのが無難、という結論で。