Edited at

クリップボードに保存されている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: