Programming」カテゴリーアーカイブ

zsh

Catalinaでデフォルトシェルが「zsh」に変わる、bashとの違いは? – 新・OS X ハッキング!(241) | マイナビニュース

Catalina 以降は Python2 等がデフォルトで入らなくなるらしいのが話題だ。
筆者はコッチのほうが重要だ、だって bash の Tips ページを作っているんだもん。
今から少し慣れておいたほうが良さそうと思い早速使ってみる。

zsh に変更するとタイトルバーの表示も zsh に変わるのね。
しかしなんだこのシンプルすぎるプロンプトは。
いや bash のプロンプトは Fedora と同じ表示になるカスタムなんだけーがさ。
早々にカスタムだ。

zsh 設定 – プロンプト –

RPROMPT って何だ?
よく解らないことは自分で試してみるのが一番早い。
~/.zshenv を作って以下を書き込み。

# Fedora like Prompt for bash
#PS1='[\u@\h \W]\$ '
# zsh
PROMPT='[%n@%m]%# '
RPROMPT='[%~]'

右に出るんかい!
長いコマンドで上に被さると自動で消える、なるほどって感じ。
今となっては bash にも tcsh にも実装って書いてあるけど。。。
関数から自力で実装する方法しか見付からないんですけど。

一般ユーザーが # ってのも気になる所だけど。
そもそも sudo しか使えないんだからココを変える意味は今では無いんだけーが。
右出しを含めてどちらのシェルか解りやすいしコレでいくかなと。

ところで macOS の bash は cd doc から tab キーで documents になった。
zsh では cd Doc と大文字小文字を合わせないと tab キー補完ができないようだ。

シェルスクリプトの覚書色々 – L’Isola di Niente

read コマンドが微妙に違う。
for 文も微妙に違う。
細かいことはもう少し調べてから。

Hello Atom

PyObjC Tips の作成が全然進まない。
原因は解っている、Visual Studio Code がイライラするからだ!
無効にしても無効にしても意図しない補完を勝手にされるのはもうウンザリ。
でも mac のエディタってイマイチなものしか。。。

そういえば Atom って初期の超不安定な頃のしか試していないや、と。
最近のはどうなっているのかな、検索してみよう。

GitHub、無償コードエディター「Atom 1.31」を正式公開 ?ファイルツリーに多くの改善 – 窓の杜

シバンでファイルの見分けができるようになっているようだ。
何だよ、vscode よりコッチのほうが絶対にいいじゃん。

Atom

早速 macOS 版 1.38 をインストール。
触り始めでレビューしても無意味なので二週間ほど使い込む。
その間、徹底的に Gedit 風にカスタマイズ。

Atom を Gedit のように使う – L’Isola di Niente

こうなった。
何だこれ、vscode での不満が全部解決したぞ。

script というシンプルな名前のパッケージが本当に素敵!
モードラインが使える!
自作Geditプラグインの html_escape が関数追加だけで使える!
coffeescript を少し調べる必要があったけど JavaScript が解るなら簡単!
イライラするだけの余計な補完をしない(超重要!)

ということで乗り換え決定。
ただひとつ、拡張関数は js でよくね?

NSView Auto Layout

NSView のレイアウト方式いろいろ – ひ?to?り?go?と

こんなの見つけた。
windowDidResize に頼らず NSView を引き延ばす手段がこんなにあったんだ。

autoresizingMask の指定
addConstraints でアンカーの指定
layout のオーバーライド

一つづつ作って試すの面倒だから NSView の上に NSView を置いて。
上記三つを全部 PyObjC でやってみた。

#!/usr/bin/env python3

from AppKit import *

RECT = ((0, 0), (300, 100))
wins = []

class TopView(NSView):
    def initWithFrame_(self, rect):
        objc.super(TopView, self).initWithFrame_(rect)
        return self

    def drawRect_(self, rect):
        # 全体にバッテンを描く
        NSColor.darkGrayColor().set()
        path = NSBezierPath.bezierPath()
        path.setLineWidth_(10)
        path.moveToPoint_((0, 0))
        path.lineToPoint_(rect.size) # タプルなのでこれでいい
        path.moveToPoint_((0, rect.size.height))
        path.lineToPoint_((rect.size.width, 0))
        path.stroke()

class SecondView(NSView):
    def initWithFrame_(self, rect):
        objc.super(SecondView, self).initWithFrame_(rect)
        self.v = TopView.alloc().initWithFrame_(RECT)
        self.addSubview_(self.v)
        return self

    def layout(self):
        # Override
        objc.super(SecondView, self).layout()
        self.v.setFrameSize_(self.frame().size)

class ThirdView(NSView):
    def initWithFrame_(self, rect):
        objc.super(ThirdView, self).initWithFrame_(rect)
        self.v = SecondView.alloc().initWithFrame_(RECT)
        self.addSubview_(self.v)
        #
        # addConstraints
        #
        self.v.setTranslatesAutoresizingMaskIntoConstraints_(False)
        self.addConstraints_([
            self.v.leftAnchor().constraintEqualToAnchor_constant_(self.leftAnchor(), 0),
            self.v.rightAnchor().constraintEqualToAnchor_constant_(self.rightAnchor(), 0),
            self.v.topAnchor().constraintEqualToAnchor_constant_(self.topAnchor(), 0),
            self.v.bottomAnchor().constraintEqualToAnchor_constant_(self.bottomAnchor(), 0)
        ])
        return self

class MyWindow(NSWindow):
    def init(self):
        objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
            RECT,
            NSTitledWindowMask | NSClosableWindowMask |
            NSResizableWindowMask | NSMiniaturizableWindowMask,
            NSBackingStoreBuffered, False)
        self.center()
        self.setTitle_('Auto Resize')
        #self.setDelegate_(self)
        # View
        self.v = ThirdView.alloc().initWithFrame_(RECT)
        self.contentView().addSubview_(self.v)
        #
        # autoresizingMask
        #
        self.v.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable) # 2+16
        #
        return self

    #def windowDidResize_(self, sender):
    #    self.v.setFrameSize_(self.contentView().frame().size)

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        window = MyWindow.new()
        window.makeKeyAndOrderFront_(window)
        wins.append(window)

class AppMenu(NSMenu):
    def init(self):
        objc.super(AppMenu, self).init()
        item_app  = NSMenuItem.new()
        self.addItem_(item_app)
        menu_app = NSMenu.new()
        item_app.setSubmenu_(menu_app)
        # quit menu
        item_quit = NSMenuItem.new()
        item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
        menu_app.addItem_(item_quit)
        return self

NSApplication.sharedApplication()
NSApp.setMainMenu_(AppMenu.new())
NSApp.setDelegate_(AppDelegate.new())
NSApp.activateIgnoringOtherApps_(True)
NSApp.run()

なるほど、全部 PyObjC からでも使えますね。
でも結局 windowDidResize が一番扱いやすいような。。。。。

NSPopUpButton, NSComboBox

NSComboBox を使ってみたけど何か変だ。
システム環境設定のコンボボックスと形が違う。
タップでプルダウンも矢印の所しか反応しないし何コレ?

Views and Controls | Apple Developer Documentation
どうやらこれは NSPopUpButton というコントロールのようだ。
GTK+ みたいに Gallery が欲しいんですけど。
Widget Gallery: GTK+ 3 Reference Manual

NSComboBox が NSTextField のサブクラス。
NSPopUpButton が NSButton のサブクラス。

items = ['YAMAHA', 'SUZUKI']

class MyView(NSView):
    def initWithFrame_(self, rect):
        objc.super(MyView, self).initWithFrame_(rect)
        #
        # NSComboBox @ NSTextField init method
        cbox = NSComboBox.labelWithString_('Select')
        w, h = cbox.frameSize() # Get Control Height
        cbox.setFrame_(((10, 10), (200, h)))
        cbox.addItemsWithObjectValues_(items)
        self.addSubview_(cbox)
        #
        # NSPopUpButton
        pop = NSPopUpButton.alloc().initWithFrame_pullsDown_(((10, 40), (200, h)), False)
        pop.addItemsWithTitles_(items)
        self.addSubview_(pop)
        #
        return self

未選択状態が必要な場合は NSComboBox を利用。
みたいな使い分けでいいのかな?
どこをタップしてもいい NSPopUpButton はタッチ操作向けだよな。
もう少し弄ってみる。

pythonhosted

あれ? https://pythonhosted.org/pyobjc/index.html が消えている。

PyObjC Document はコッチに移動(?)したようだ。
Introduction ? PyObjC – the Python to Objective-C bridge
以前からあったのかどうかは知らない、基本 Fedora 屋なので。

というわけで NSTextField Tips 追加。
NSTextField – L’Isola di Niente
短いけど実用には充分にしたつもり。

しかし textDidChange: は何故デリゲートではなくメソッドなんだよ。
NSButton に至っては target, action 指定だし、この統一感の無さが macOS の中身。
macOS の洗練された見た目と統一された操作性はこの糞みたいな Cocoa で作られている。
GTK+ も GTK3 にならなかったらこんな感じになっていたんだろうな。

次は NSTextView にしようと思ったけど。
NSTextView – AppKit | Apple Developer Documentation
Rich Text のことばかりみたいだなぁ、ヤル気しねぇ。
NSSlider, NSComboBox あたりにしよう、のんびりと。