Java
dos
jshell
クソアプリ

クリップボードに保存されているJavaコードを実行する。

はじめに

ちょっとしたJavaプログラムを試したいことありますよね?
image.png

Java9からREPLツールとしてJShellが搭載されました。
Java11では事前のjavacなしでJavaファイルの実行が出来るようになりました。
あとpaiza.IOとかのオンライン実行環境も便利ですね。

確実に手軽に実行できるようにはなってはいます。
ただ、もっと簡単にプログラム試せないかしら・・・。
せや:bangbang:クリップボードに張り付いているJavaコード実行できたらいいんじゃないかしら・・・:point_up:

ということで、表題のクリップボードに保存されているJavaコードを実行するを思いつきました。

軽くインターネット調べてみたものの、自分で調べた限りは出てこなかったので作ってみます。
(そもそも必要ないから出てこないんじゃ・・・:poop:もはや何か臭う・・:poop:というのは置いといて。)

つくってみた

仕掛けとしては、クリップボードから文字列取得し、その文字列をjshellに引き渡すという単純な仕掛けですね。
ちなみにJShellにはデフォルトで以下のパッケージがimportされています。

jshell> /import
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*

まずはクリップボードから文字列取得する部分を作ります。
別になんでも良いのですが、Javaで書きました。

PrintClipboardString.java
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
 * クリップボードから文字列データを出力します。
 */
public class PrintClipboardString {
    /**
     * メイン
     */
    public static void main(String[] args) {
        System.out.println(getClipboardString());
    }
    /**
     * クリップボードから文字列データを返します。
     * 
     * @return クリップボードの文字列データを返します。文字列データでない場合はnullを返します。
     */
    public static String getClipboardString() {
        Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();

        try {
            return (String) clip.getData(DataFlavor.stringFlavor);
        } catch (UnsupportedFlavorException e) {
            return null;
        } catch (IOException e) {
            return null;
        }
    }
}

次はこのPrintClipboardString.javaを利用するバッチファイル(DOS)作ります。
クリップボードから文字列データを取得して、JShellに引き渡す役割ですね。

clipbord_jshell.bat
@echo off
setlocal enabledelayedexpansion

set CLIP_BOARD=
for /f "usebackq tokens=*" %%i in (`java PrintClipboardString`) do (
    set CLIP_BOARD=!CLIP_BOARD!^
%%i
)
echo =============
echo  ソース
echo =============
echo !CLIP_BOARD!
echo.

echo =============
echo  実行結果
echo =============
echo !CLIP_BOARD! | jshell -
echo.

pause

これDOSなのでコマンド実行結果を扱う部分の考慮でfor文使っていますが、Unix系シェルだと普通にバッククォート使えるので簡単だと思います。

つかってみた

1.文字列出力してみた。

System.out.println("hello");
↑このテキストをコピー(クリップボードに格納)して、バッチファイル実行します。

$clipbord_jshell.bat
=============
 ソース
=============
System.out.println("hello");

=============
 実行結果
=============
hello

続行するには何かキーを押してください . . .

あらいい感じ:sunny:

2.Mathクラス使ってみた。

System.out.println(Math.random());
System.out.println(Math.random());
System.out.println(Math.random());

↑このテキスト3行をコピー(クリップボードに格納)して、バッチファイル実行します。

$clipbord_jshell.bat
=============
 ソース
=============
System.out.println(Math.random());System.out.println(Math.random());System.out.println(Math.random());

=============
 実行結果
=============
0.13619188697681628
0.6036857063092008
0.7567411771330568

続行するには何かキーを押してください . . .

ソースが1行表示されてしまいましたが・・・、複数行でも実行結果はいい感じですね。
JShelljava.math.*がimport済みなので、別途importせずとも実行できました。

3.クリスマスまであと何日か数えてみた。

日付操作系って比較的試したいケースが多いと思うんですよね。

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
LocalDateTime d = LocalDateTime.now();
LocalDateTime c = LocalDateTime.of(2018, 12, 25 , 23, 59);
System.out.println("クリスマスまであと・・・" + ChronoUnit.DAYS.between(d, c) + "日");
↑このテキスト5行をコピー(クリップボードに格納)して、バッチファイル実行します。

$clipbord_jshell.bat
=============
 ソース
=============
import java.time.LocalDateTime;import java.time.temporal.ChronoUnit;LocalDateTime d = LocalDateTime.now();LocalDateTime c = LocalDateTime.of(2018, 12,
 25 , 23, 59);System.out.println("クリスマスまであと・・・" + ChronoUnit.DAYS.between(d, c) + "日");

=============
 実行結果
=============
クリスマスまであと・・・20日

続行するには何かキーを押してください . . .

でけたぁ:relaxed:

おわりに

・インターネットからコピってきたプログラム(完成しているプログラム)を実行するのには使えそう。
・いちいち標準出力(System.out~)しないといけないのが面倒くさい。
・間違えてJavaコード以外をコピーして実行しがち。どえらい怒られる:no_good_tone3:
・行コメントが途中に入ったら、後続がコメントと見なされてロジックが全く評価されない。(ここは改善の余地ありそう?)
・やはりゴミツール・・な気もするけど、やはり我が子はかわいい:poop:
・それセキュリティ大丈夫なんか。byインフラエンジニア
・反省はしていない。

以上、メリークリスマスでございます:christmas_tree: