VS Code - z/OS連携[Zowe Explorer V3編] (2)基本操作

# はじめに
ここでは、Zowe Explorer、Z Open Editorを使用した基本的な設定、操作(無償でできる範囲)について解説します。

## 関連記事

[VS Code - z/OS連携[Zowe Explorer V3編] (1)概要, 基本構成](https://qiita.com/tomotagwork/items/4eb3e51b01b8db76cefc)
[VS Code - z/OS連携[Zowe Explorer V3編] (2)基本操作](https://qiita.com/tomotagwork/items/7e6ab9970d4b8a1fb219)
[VS Code - z/OS連携[Zowe Explorer V3編] (3)VS Codeからのユーザー・ビルド](https://qiita.com/tomotagwork/items/45e46ca55e38cec44a58)

# 全体像

当記事で示す操作は、基本的には以下のような構成をベースとしたものを想定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/1eaec167-a4a6-5cf3-a18d-77f1c9669de8.png)


# VS Code設定
まず、VS Codeの設定周りについて補足しておきます。一旦、設定方法や構成ファイルの考え方をざっと見て、具体的な設定方法については後続の操作例と合わせてみていきます。

## VS Codeワークスペース
VS Codeでは"ワークスペース"という考え方があり、ワークスペース単位に独自の設定などを行うことができます。OS上の1つのディレクトリを1ワークスペースとして管理する Single-folderワークスペースと、複数のディレクトリのセットをまとめて1ワークスペースとして管理する Multi-rootワークスペースという使い方があります。

参考:
[What is a VS Code "workspace"?](https://code.visualstudio.com/docs/editor/workspaces)

ここでは Single-folderワークスペースの利用をベースとして具体例を見ていきたいと思います。
※2025年1月時点ではMulti-rootワークスペースだと、後続のZAPPファイルの挙動に怪しい所があるのでSingle-folderワークスペースを使用するのがおすすめ。

### Single-folderワークスペース作成例

VS Codeを開きます。ワークスペースを開いている場合は[ファイル]-[ワークスペースを閉じる]を選択してワークスペースを閉じておきます。つまりカラの状態でVS Codeを立ち上げた状態にしておきます。
ここで、メニューから[ファイル]-[フォルダーをワークスペースに追加]を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/66f4e14c-b2ae-4beb-ddf8-de97c57f997f.png)

適当なフォルダを作成して指定。(ここでは`c:\y\VSCode_workspace\ZoweTest01`を指定)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/a838e9b8-d292-f2ed-661c-ca679a94340f.png)

「はい、作成者を信頼します」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/a1ea5c6f-6829-9ad0-9742-0be8618bdf25.png)

`c:\y\VSCode_workspace\ZoweTest01`に紐づけられたワークスペースが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/bb82bfea-f1bf-4431-cf9f-106c1bfc74d2.png)

続けてVS Codeの設定変更をしてみます。
メニューから[ファイル]-[ユーザー設定]-[設定]を選択すると、各種設定が行えるViewが開きます。
検索窓の下に"ユーザー", "ワークスペース"というタブがあることからも分かるように、設定をこれらのレベルで使い分けることができます。ワークスペース単位で設定を切り替えたい場合は"ワークスペース"タブで設定を行えばよいということになります。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ac041a58-3297-e4bb-0a03-d9ea7756c6f4.png)

例えば上の例では、IBM Z Open Editor関連の設定で、ワークスペースレベルで「PL1: Disable Problem」というプロパティーにチェックを入れてみました。
このようなワークスペースレベルの設定変更情報は、`.vscode\settings.json`ファイルが作成されこのファイル内に保持されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b6a17b07-2e7b-aeb1-ea7c-d9961adfef00.png)

ユーザーレベルのプロパティー設定は、`<ユーザーのホームディレクトリ>\AppData\Roaming\Code\User\setting.json`ファイルに保存されます。

ちなみに、VS CodeのExtensionは、ワークスペース単位で無効化することができます。たくさんExtensionを入れて分かりにくくなってしまった場合、ワークスペース毎に不要なExtensionは無効化することで画面を簡素化するといった制御も可能です。
例: Extensionの「無効にする」の右側のプルダウンメニューにある「無効にする(ワークスペース)」を選択すると、その時点で開いているワークスペース上でのみ当該Extensionが無効化されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/4bf9dfca-bcd8-ab5d-6738-654bf2c13520.png)


こんな感じでワークスペースの制御が行われています。
※この辺りはZowe Explorerに関係なく、一般的なVS Codeの話です。

## z/OS接続構成ファイル

z/OSとの接続構成情報は、グローバル/プロジェクトの2つのレベルで保持できます。
"グローバル"はVS Codeを使用するユーザーの単位で保持され、当該ユーザーで使用する全ての環境で有効となります。これは先の記事で作成した、`<ユーザーのホームディレクトリ>\.zowe\zowe.config.json`ファイルに該当します。
"プロジェクト"レベルはVS Codeのワークスペース単位で保持され、ワークスペースの範囲で有効となります。

| 種類 | 構成ファイル | 有効範囲 |
|-|-|-|
|グローバル    |`<ユーザーのホーム>\.zowe\zowe.config.json` | 当該ユーザーの全環境 |
|プロジェクト  |`<ワークスペースのトップ>\zowe.config.json`  | ワークスペース |


Zowe Explorer view の 「データ・セット」の右側の「+」アイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/80123627-a7bd-3fa7-8227-8537bb3af398.png)

以下のようにグローバル/プロジェクトの選択肢が表示されます。ここでは「プロジェクト」を選択してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/9c8c43a5-f919-cc6c-2500-ac12a7e28efc.png)

すると、当該ワークスペースに紐づけられたフォルダ(今回のケースだと`ZoweTest01`ディレクトリ下)に、`zowe.config.json`ファイルが作成されて、z/OSとの接続構成の雛形が作成されます。先の例と同様に、このファイルでz/OSとの接続定義を行うことができます。

<details><summary><font color="blue">構成ファイル例</font></summary><div>

```json:ZoweTest01\zowe.config.json
{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar2": {
            "properties": {
                "host": "tzMyTest02"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 10443
                    }
                },
                "ssh": {
                    "type": "ssh",
                    "properties": {
                        "port": 22,
                        "privateKey": "C:\\Users\\A00527JP6\\.ssh\\TechZone\\ssh_private_key_MyTest02.pem"
                    }
                }
            }
        },
        "lpar3": {
            "properties": {
                "host": "eplex1"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 10443
                    }
                },
                "ssh": {
                    "type": "ssh",
                    "properties": {
                        "port": 22,
                        "privateKey": "C:\\Users\\A00527JP6\\.ssh\\id_rsa"
                    }
                }
            }
        },
        "project_base": {
            "type": "base",
            "properties": {
                "rejectUnauthorized": false
            },
            "secure": [
                "user",
                "password"
            ]
        }
    },
    "defaults": {
        "zosmf": "lpar2.zosmf",
        "base": "project_base"
    },
    "autoStore": true,
    "plugins": []
}
```

</div></details>

上の例では、lpar2, lpar3という名前で、2つのz/OSに対する接続定義をプロジェクト単位に追加で定義しています。

再度、Zowe Explorer view の 「データ・セット」の右側の「+」アイコンをクリックしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/80123627-a7bd-3fa7-8227-8537bb3af398.png)

すると、上で追加した定義がプルダウンから選択できるようになっています。lpar3.zosmfを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/e6fc1763-a86f-f6ec-9e2f-3b5fd5d1a0b7.png)

はいを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/796b3aad-a61c-84ee-6877-566da0237503.png)

ZOWE EXPLORER viewにz/OS接続用プロファイルのエントリーが追加されるので、その環境に対してもユーザー/パスワードを指定することでアクセスできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/0a18dd76-7027-79ec-4a14-20718eef41ec.png)

※同じプロパティがグローバルとプロジェクトの両方に指定していた場合は、基本的にプロジェクトの方が優先されます。
参考: [Using multiple properties found in multiple profiles](https://docs.zowe.org/stable/user-guide/cli-using-understand-profiles-configs#using-multiple-properties-found-in-multiple-profiles)

### z/OS接続構成ファイル補足

構成ファイルの構造を簡単に補足します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3a763685-b108-b6f6-75bd-f2514ccde460.png)

構成ファイルの構造は、構成ファイル作成時に一緒に作成されるJSON Schemaファイルにて定義されています。
<details><summary><font color="blue">参考: zowe.schema.json</font></summary>

```json:zowe.shema.json
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$version": "1.0",
    "type": "object",
    "description": "Zowe configuration",
    "properties": {
        "profiles": {
            "type": "object",
            "description": "Mapping of profile names to profile configurations",
            "patternProperties": {
                "^\\S*$": {
                    "type": "object",
                    "description": "Profile configuration object",
                    "properties": {
                        "type": {
                            "description": "Profile type",
                            "type": "string",
                            "enum": [
                                "zosmf",
                                "tso",
                                "ssh",
                                "rse",
                                "base"
                            ]
                        },
                        "properties": {
                            "description": "Profile properties object",
                            "type": "object"
                        },
                        "profiles": {
                            "description": "Optional subprofile configurations",
                            "type": "object",
                            "$ref": "#/properties/profiles"
                        },
                        "secure": {
                            "description": "Secure property names",
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "uniqueItems": true
                        }
                    },
                    "allOf": [
                        {
                            "if": {
                                "properties": {
                                    "type": false
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "title": "Missing profile type"
                                    }
                                }
                            }
                        },
                        {
                            "if": {
                                "properties": {
                                    "type": {
                                        "const": "zosmf"
                                    }
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "type": "object",
                                        "title": "z/OSMF Profile",
                                        "description": "z/OSMF Profile",
                                        "properties": {
                                            "host": {
                                                "type": "string",
                                                "description": "The z/OSMF server host name."
                                            },
                                            "port": {
                                                "type": "number",
                                                "description": "The z/OSMF server port.",
                                                "default": 443
                                            },
                                            "user": {
                                                "type": "string",
                                                "description": "Mainframe (z/OSMF) user name, which can be the same as your TSO login."
                                            },
                                            "password": {
                                                "type": "string",
                                                "description": "Mainframe (z/OSMF) password, which can be the same as your TSO password."
                                            },
                                            "rejectUnauthorized": {
                                                "type": "boolean",
                                                "description": "Reject self-signed certificates.",
                                                "default": true
                                            },
                                            "certFile": {
                                                "type": "string",
                                                "description": "The file path to a certificate file to use for authentication"
                                            },
                                            "certKeyFile": {
                                                "type": "string",
                                                "description": "The file path to a certificate key file to use for authentication"
                                            },
                                            "basePath": {
                                                "type": "string",
                                                "description": "The base path for your API mediation layer instance. Specify this option to prepend the base path to all z/OSMF resources when making REST requests. Do not specify this option if you are not using an API mediation layer."
                                            },
                                            "protocol": {
                                                "type": "string",
                                                "description": "The protocol used (HTTP or HTTPS)",
                                                "default": "https",
                                                "enum": [
                                                    "http",
                                                    "https"
                                                ]
                                            },
                                            "encoding": {
                                                "type": "string",
                                                "description": "The encoding for download and upload of z/OS data set and USS files. The default encoding if not specified is IBM-1047."
                                            },
                                            "responseTimeout": {
                                                "type": "number",
                                                "description": "The maximum amount of time in seconds the z/OSMF Files TSO servlet should run before returning a response. Any request exceeding this amount of time will be terminated and return an error. Allowed values: 5 - 600"
                                            }
                                        },
                                        "required": []
                                    },
                                    "secure": {
                                        "items": {
                                            "enum": [
                                                "user",
                                                "password"
                                            ]
                                        }
                                    }
                                }
                            }
                        },
                        {
                            "if": {
                                "properties": {
                                    "type": {
                                        "const": "tso"
                                    }
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "type": "object",
                                        "title": "TSO Profile",
                                        "description": "z/OS TSO/E User Profile",
                                        "properties": {
                                            "account": {
                                                "type": "string",
                                                "description": "Your z/OS TSO/E accounting information."
                                            },
                                            "characterSet": {
                                                "type": "string",
                                                "description": "Character set for address space to convert messages and responses from UTF-8 to EBCDIC.",
                                                "default": "697"
                                            },
                                            "codePage": {
                                                "type": "string",
                                                "description": "Codepage value for TSO/E address space to convert messages and responses from UTF-8 to EBCDIC.",
                                                "default": "1047"
                                            },
                                            "columns": {
                                                "type": "number",
                                                "description": "The number of columns on a screen.",
                                                "default": 80
                                            },
                                            "logonProcedure": {
                                                "type": "string",
                                                "description": "The logon procedure to use when creating TSO procedures on your behalf.",
                                                "default": "IZUFPROC"
                                            },
                                            "regionSize": {
                                                "type": "number",
                                                "description": "Region size for the TSO/E address space.",
                                                "default": 4096
                                            },
                                            "rows": {
                                                "type": "number",
                                                "description": "The number of rows on a screen.",
                                                "default": 24
                                            }
                                        },
                                        "required": []
                                    }
                                }
                            }
                        },
                        {
                            "if": {
                                "properties": {
                                    "type": {
                                        "const": "ssh"
                                    }
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "type": "object",
                                        "title": "z/OS SSH Profile",
                                        "description": "z/OS SSH Profile",
                                        "properties": {
                                            "host": {
                                                "type": "string",
                                                "description": "The z/OS SSH server host name."
                                            },
                                            "port": {
                                                "type": "number",
                                                "description": "The z/OS SSH server port.",
                                                "default": 22
                                            },
                                            "user": {
                                                "type": "string",
                                                "description": "Mainframe user name, which can be the same as your TSO login."
                                            },
                                            "password": {
                                                "type": "string",
                                                "description": "Mainframe password, which can be the same as your TSO password."
                                            },
                                            "privateKey": {
                                                "type": "string",
                                                "description": "Path to a file containing your private key, that must match a public key stored in the server for authentication"
                                            },
                                            "keyPassphrase": {
                                                "type": "string",
                                                "description": "Private key passphrase, which unlocks the private key."
                                            },
                                            "handshakeTimeout": {
                                                "type": "number",
                                                "description": "How long in milliseconds to wait for the SSH handshake to complete."
                                            }
                                        },
                                        "required": []
                                    },
                                    "secure": {
                                        "items": {
                                            "enum": [
                                                "user",
                                                "password",
                                                "keyPassphrase"
                                            ]
                                        }
                                    }
                                }
                            }
                        },
                        {
                            "if": {
                                "properties": {
                                    "type": {
                                        "const": "rse"
                                    }
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "type": "object",
                                        "title": "IBM RSE API Zowe Profile",
                                        "description": "A profile to issue commands to a z/OS system with a working Zowe REST server,Mediation Layer, or IBM RSE (Remote System Explorer) API server installation.",
                                        "properties": {
                                            "host": {
                                                "type": "string",
                                                "description": "The z/OS host name running the Zowe REST API."
                                            },
                                            "port": {
                                                "type": "number",
                                                "description": "The server port used by the REST API.",
                                                "default": 6800
                                            },
                                            "user": {
                                                "type": "string",
                                                "description": "The user name for the Zowe REST API operations."
                                            },
                                            "password": {
                                                "type": "string",
                                                "description": "The password of the user for the Zowe REST API operations."
                                            },
                                            "rejectUnauthorized": {
                                                "type": "boolean",
                                                "description": "Reject self-signed certificates.",
                                                "default": true
                                            },
                                            "basePath": {
                                                "type": "string",
                                                "description": "The base path of the API for the REST API operations.",
                                                "default": "rseapi"
                                            },
                                            "protocol": {
                                                "type": "string",
                                                "description": "http or https, depending whether a TLS handshake is required to access REST API.",
                                                "default": "https"
                                            },
                                            "encoding": {
                                                "type": "string",
                                                "description": "The encoding for download and upload of z/OS data set and USS files. The encoding should be specified in the form of \"IBM-1047\"."
                                            },
                                            "tokenType": {
                                                "type": "string",
                                                "description": "JWT type assigned to profile when \"zowe rse auth login\" is used for authentication."
                                            },
                                            "tokenValue": {
                                                "type": "string",
                                                "description": "JWT value assigned to profile when \"zowe rse auth login\" is used for authentication."
                                            },
                                            "tokenExpiration": {
                                                "type": "string",
                                                "description": "JWT expiration assigned to profile when \"zowe rse auth login\" is used for authentication."
                                            }
                                        },
                                        "required": []
                                    },
                                    "secure": {
                                        "items": {
                                            "enum": [
                                                "user",
                                                "password",
                                                "tokenValue"
                                            ]
                                        }
                                    }
                                }
                            }
                        },
                        {
                            "if": {
                                "properties": {
                                    "type": {
                                        "const": "base"
                                    }
                                }
                            },
                            "then": {
                                "properties": {
                                    "properties": {
                                        "type": "object",
                                        "title": "Base Profile",
                                        "description": "Base profile that stores values shared by multiple service profiles",
                                        "properties": {
                                            "host": {
                                                "type": "string",
                                                "description": "Host name of service on the mainframe."
                                            },
                                            "port": {
                                                "type": "number",
                                                "description": "Port number of service on the mainframe."
                                            },
                                            "user": {
                                                "type": "string",
                                                "description": "User name to authenticate to service on the mainframe."
                                            },
                                            "password": {
                                                "type": "string",
                                                "description": "Password to authenticate to service on the mainframe."
                                            },
                                            "rejectUnauthorized": {
                                                "type": "boolean",
                                                "description": "Reject self-signed certificates.",
                                                "default": true
                                            },
                                            "tokenType": {
                                                "type": "string",
                                                "description": "The type of token to get and use for the API. Omit this option to use the default token type, which is provided by 'zowe auth login'."
                                            },
                                            "tokenValue": {
                                                "type": "string",
                                                "description": "The value of the token to pass to the API."
                                            },
                                            "certFile": {
                                                "type": "string",
                                                "description": "The file path to a certificate file to use for authentication.\n\nNote: The CLI does not support certificate files that require a password. For more information, search Troubleshooting PEM Certificates in Zowe Docs."
                                            },
                                            "certKeyFile": {
                                                "type": "string",
                                                "description": "The file path to a certificate key file to use for authentication"
                                            }
                                        },
                                        "required": []
                                    },
                                    "secure": {
                                        "items": {
                                            "enum": [
                                                "user",
                                                "password",
                                                "tokenValue"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        },
        "defaults": {
            "type": "object",
            "description": "Mapping of profile types to default profile names",
            "properties": {
                "zosmf": {
                    "description": "Default zosmf profile",
                    "type": "string"
                },
                "tso": {
                    "description": "Default tso profile",
                    "type": "string"
                },
                "ssh": {
                    "description": "Default ssh profile",
                    "type": "string"
                },
                "rse": {
                    "description": "Default rse profile",
                    "type": "string"
                },
                "base": {
                    "description": "Default base profile",
                    "type": "string"
                }
            }
        },
        "autoStore": {
            "type": "boolean",
            "description": "If true, values you enter when prompted are stored for future use"
        }
    }
}
```

</details>









## zapp.yml

IBM Z Open Editor Extensionは、各種z/OSのアプリケーション開発支援機能を提供します。それら各種機能に関して環境依存のプロパティは、VS Codeの設定([ファイル]-[ユーザー設定]-[設定])にて設定できます。
参考: [IBM Z Open Editor - Setting preferences](https://ibm.github.io/zopeneditor-about/Docs/setting_preferences.html)

一方で、アプリケーション毎に個別に制御したい設定については、別途ZAPPファイルとよばれるファイル(YAML or JSON)で管理できるようになっています。これはGitなどのソース管理システムとの親和性を考慮して導入された仕組みです。例えば、COBOLソースに含まれるCOPYBOOKの探索パスなどをZAPPファイルで指定することができます。
参考: [Configuring your applications with ZAPP files](https://ibm.github.io/zopeneditor-about/Docs/zapp.html)

ここではZAPPファイルの簡単な利用例を見ていきたいと思います。

先に作成したワークスペースに、COBOLのソース、COPYBOOK等が含まれたフォルダを追加します。(ここでは`Test01`)
VS Code上でCOBOLファイル(拡張子cbl)を選択してVS Code上のエディターで開いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/c737a95b-b3d2-63a4-3b3d-ce656cb3d370.png)

デフォルトだとこのように最初にz/OSアプリケーションを開いたタイミングでZAPPファイルが存在していない場合、ZAPPファイルの雛形が自動的に作成されます。ZAPPファイルは当該ワークスペースのトップのフォルダ内に作成されます。今回の場合、`ZoweTest01\zpp.yaml` です。

※ZAPPファイルが自動生成されるは、IBM Z Open Editorのプロパティ 「Zapp: Generate Zapp On Demand」(zopeneditor.zapp.generateZappOnDemand)がデフォルトで有効化されているためです。これを無効化するとZAPPファイルの自動生成は抑止されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/943012ed-fe23-d1a0-1456-9ee91962600b.png)

以下の辺りのサンプルを参考に、ZAPPファイルを編集します。
参考:
[Configuring your applications with ZAPP files](https://ibm.github.io/zopeneditor-about/Docs/zapp.html)
[zopeneditor-sample/zapp.yaml](https://github.com/IBM/zopeneditor-sample/blob/main/zapp.yaml)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/8bdea24f-984d-cd8a-ab8e-b843cd674b99.png)

<details><summary><font color="blue">ZAPPファイル例</font></summary><div>

```yaml:ZoweTest01\zapp.yaml
name: ZoweTest01
description: Zowe Explorer Test
author: ISE
propertyGroups:
  - name: cobol-copybooks
    language: cobol
    libraries:
      - name: syslib
        type: local
        locations:
          - '**/copybook'
```

</div></details>

これでCOBOLソースからCOPYBOOK参照(カーソルをCOPY句のメンバー名に合わせてホバー表示)ができればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/fedcf657-088f-56df-9199-dcaaeffbf6d9.png)

# 基本操作例

## ソース編集

### 言語の識別
COBOLやPL/Iなどのソースを編集する際に、対象のファイルやPDSメンバーをエディターで開くことになりますが、この時操作対象の言語によってエディターは動作が変わります。分かりやすい所でいえば、COBOLのソースを開いた場合はCOBOLの構文に従ってソースを解釈してキーワードごとに色分け表示をしてくれたりします。
どのメンバー/ファイルをどの言語として認識するかというのは、一定のルールに従って判断されます。

#### ローカル・ファイル
ローカルのファイル(PC上のファイル)をVS Codeのエディターで編集したい場合、一般的に各ファイルにはファイルの内容に応じた拡張子が付けられますので、その拡張子を元にファイルの内容を判断します。例えば`*.cbl`や`*.cpy`であればCOBOL、`*.pli`や`*.inc`であればPL/Iといった具合です。

参考:
[Local file associations](https://ibm.github.io/zopeneditor-about/Docs/setting_fileassociations.html#local-file-associations)

デフォルトで認識される拡張子は以下の通りです。

| Language | VS Code Language ID | Default File Extensions |
|:-:|:-:|:-:|
|Enterprise COBOL       |cobol |.cbl .cpy .cob .copy .copybook .cobol .cobcopy |
|Enterprise PL/I        |pl1   |.pli .pl1 .pc .pci .plinc .pcx .inc .include |
|Z High Level Assembler |hlasm |.s .assemble .asm .hla .hlasm .copyasm .macasm .bms .mac .dbd .mfs .pcb |
|REXX                   |rexx  |.rexx |
|JCL                    |jcl   |.jcl |

基本的にはこの範囲でファイルのネーミングルールを決めるのがおすすめですが、追加することも可能です。その場合は設定(setting.json)のプロパティーで追加指定可能です。

#### PDSメンバー
VS CodeからZowe Explorerにてz/OS上のMVSデータセット上のソース(PDSメンバー)を開いて編集する場合、対象となるPDSメンバーには拡張子が存在しませんので、ローカルファイルとは別のソース認識のルールが必要となります。

参考:
[Remote file associations](https://ibm.github.io/zopeneditor-about/Docs/setting_fileassociations.html#remote-file-associations)

これは、言語ごとのプロパティーが容易されているのでVS Codeの設定(setting.json)で指定可能です。例えばCOBOLであれば、「Datasets: Cobol Datasets」(zopeneditor.datasets.cobolDatasets)にて指定可能で、デフォルトで以下のような設定になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/85583d70-59ef-46dd-1454-50814d3c6cc1.png)
ここに指定されているネーミングルールのPDSデータセットに含まれるメンバーをVS Codeエディターで開いた場合は中身をCOBOLとみなして構文解釈することになります。例えば、`USER01.APP01.COBOL`、`TEST.XXX.YYY.COBCOPY` といったPDSに含まれるメンバーはCOBOLと解釈されます。
ちょっと分かりにくいのは、このプロパティーの変更は別のプロパティー"file.associations"を変更するためのものであって、実質的には"file.associations"の定義が動作に反映されます。
例えば、デフォルトのエントリーに加えて、".PGMSOR"というエントリをCobol Datasetsに追加したとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/7e94af65-58e2-8d6c-2ba5-6fd4c6834c7d.png)

すると、自動的に「Files: Associations」のプロパティが以下のように更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5357e20b-f6a1-910e-0651-f5a608ab13b8.png)
デフォルトのパターンに加えて、「PGMSOR」を含むパターンが追記されました。
(削除や変更をする場合、こちらのプロパティも合わせて整合性をとる必要があるのでご注意ください)

参考:
[Using the VS Code files.associations setting](https://ibm.github.io/zopeneditor-about/Docs/setting_fileassociations.html#using-the-vs-code-files-associations-setting)

上の設定を追加した後に、Zowe Explorerからz/OSに接続して`xxx.PGMSOR`に含まれるメンバーを開くと、COBOLと認識されてCOBOL構文に従ってソースが解釈され、以下のように色分け表示されることになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5cf71172-4460-c6e3-5313-4ac610418544.png)
画面の右下に"COBOL"と表示されていることからも、このソースがCOBOLとして認識されていることが分かります。この右下の"COBOL"部分をクリックして解釈させる言語を明示的に切り替えることも可能です。


### COPYBOOK/INCLUDEファイル参照

ソース本体から別のファイルを参照しているケースがあります。COBOLだとCOPY文、PL/IだとINCLUDE文で他のファイルを参照してデータ定義を取り込んだりします。VS Codeではこのような外部ファイル参照を認識して支援する機能が提供されています。この時外部ファイルをどこから探索するか、探索パスをプロパティーで指定することができます。これはZAPPファイルで指定できます。

参考: 
[Setting property groups](https://ibm.github.io/zopeneditor-about/Docs/setting_propertygroup.html)

以降、COBOLの例で説明します。
ソース本体(参照元)のファイルと、COPYBOOK(参照先)のファイルが、それぞれどこにあるか(ローカルPC上 or z/OS上)を意識する必要があります。

まず、ソース本体(参照元)のファイルの配置場所についてですが、ローカル(PC上)のファイルを開く場合はVS Codeのエクスプローラーviewから対象のフォルダにあるソース本体を選択してエディタで開きます。
z/OS上のPDSメンバーの場合はVS CodeのZowe Explorer viewからz/OSに接続し対象のPDSにあるメンバーを選択してエディタで開きます。z/OS上のファイルをVS Codeで開く際は、ローカルPC上にソースがダウンロードされてそれをエディタで開いているイメージですので、その後のCOPYBOOK参照に関する挙動はローカル・ファイルを開いた場合と基本的には同様です。

さて、ローカルファイルにしろリモートのファイルにしろ、エディターで開いたソースの中にCOPY文で他のファイルを参照しているステートメントが含まれていた場合、構文チェックなどを行うために参照先ファイルもロードされます。参照している別ファイルの探索パスは、ZAPPファイル中のPropertyGroup内に、以下のように指定することができます。

```yaml:zapp.yaml例
name: ZoweTest01
description: Zowe Explorer Test
author: ISE
propertyGroups:
  - name: cobol-copybooks
    language: cobol
    libraries:
      - name: syslib
        type: local
        locations:
          - '**/copybook'
          - '**/copybook2'
      - name: syslib
        type: mvs
        locations:
          - CICSSHR.CICS004.COPYLIB
```

まず、propertyGroups以下に適当な名前のプロパティー・グループを定義します。ここでは、`language: cobol`を指定し、COBOL言語に関するプロパティーを定義しています。
`libraries`以下に、`syslib`という名前の定義を追加することで、参照先COPYBOOK探索場所を指定することができます。ソース本体(参照元)がローカル/リモートのいずれであっても、参照先ファイルの探索場所はローカル/リモートどちらも指定可能です。
COPYBOOKの探索場所は、ZAPPファイル上の `type` および `locations`で指定します。ローカル・ファイルを探索させたい場合は`type: local`を指定し`locations:`にPC上のディレクトリパスを指定します。リモート・ファイルを探索させたい場合は`type: mvs`を指定し`locations:`にリモートのMVSデータセットを指定します。
上の例のように、local, mvs のタイプを両方指定することもできますし、各々複数のディレクトリ、データセットを指定することができます。ZAPPファイルに定義された順番に上から探索され、最初に見つかったファイルが参照されます。

<font color="red">※注意</font>
リモート・ファイルの探索パスを指定するプロパティとしてはデータセット名のみで、接続先z/OSを識別するオプションがありません。つまりZAPPファイル上では、どのz/OS環境を探索しにいくかというのを指定することはできません。`type: mvs`を指定した時に探索されるz/OS環境は、VS Codeの設定(settings.json)にて指定します。

Zopeneditor: Zowe プロパティで、defaultCliProfile の項目に、探索先のz/OS環境への接続プロファイル(z/OSMF or RSE)を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/97dd6eca-0e6a-aa09-e239-7078be81e45a.png)

setting.jsonだと以下のイメージです。

```json: settings.json抜粋
...
"zopeneditor.zowe": {
    "defaultCliProfile": "lpar1.zosmf"
},
...
```

ZAPPファイルにてプロパティー・グループの`type:mvs`で指定されたライブラリについては、このdefaultCliProfileに指定されたz/OS環境上から探索されることになります。

このように、ZAPPファイルに記述したsyslib指定に従い参照しているファイルが見つかると、そのファイルの中身もロードされ、COBOLソースの構文解析が行われることになります。
先に示したように、COPYステートメントで指定したCOPYBOOKメンバー名にカーソルをあてるとホバーで内容が表示されますし、COPYBOOK内で定義された変数の解釈も行われて構文解析結果としてエディター上に反映されます(COPYBOOK参照がうまく機能しないと、未定義変数が使われていると判断されて構文エラーとなる)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/fedcf657-088f-56df-9199-dcaaeffbf6d9.png)

PL/Iについても同様にZAPPファイルのプロパティー・グループで制御可能です。以下、PL/IのINCLUDEファイル探索パスも指定したZAPPファイルの例です。

```yaml:zapp.yaml例
name: ZoweTest01
description: Zowe Explorer Test
author: ISE
propertyGroups:
  - name: cobol-copybooks
    language: cobol
    libraries:
      - name: syslib
        type: local
        locations:
          - '**/copybook'
          - '**/copybook2'
      - name: syslib
        type: mvs
        locations:
          - CICSSHR.CICS004.COPYLIB
  - name: pli-includes
    language: pl1
    libraries:
      - name: syslib
        type: local
        locations:
          - '**/INCLUDES'
      - name: syslib
        type: mvs
        locations:
          - CICSSHR.CICS004.INCLUDES
```

### 文字コード

z/OS上のリソースをPCOMなどの3270端末エミュレーターで参照している限りにおいては文字コードを直接意識することは少ないですが、VS Codeからz/OS上のリソースを扱う場合は、操作ごとに文字コードを意識する必要があります。
例えば、Zowe Explorerにてz/OS上のPDSメンバーをエディターで開く場合、z/OS上のメンバーがPC上に転送されて表示されることになりますが、この時EBCDICからUTF-8に文字コード変換が行われます。エディター上で内容を変更して保存する際は、逆にUTF-8からEBCDICへの変換が行われてz/OSにアップロードされます。
これらの操作を行う際、z/OSMF接続を行っている場合、内部的にはz/OSMF提供のREST APIが使用されます。z/OSMF用の接続構成ファイル(zowe.settings.json)のプロパティー`encoding`を指定することで、UTF-8⇔EBCDIC変換におけるEBCDIC側の文字コードを指定することができます。

z/OSMF接続での文字コード指定例:

```json:zowe.config.json抜粋
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 10443,
                        "encoding": "IBM-1399"
                    }
                },
```

このように、日本語対応のコードページを指定することで、日本語を含むソースの編集が行えるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/82d2f6f3-7337-4236-6161-a3542a96bd4e.png)

※2025年1月時点のZ Open Editor V5.1.0では、DBCSのハンドリングが不十分で、SO/SIを含む桁ずれの構文チェックが甘かったり、半角カタカナの前後にもSO/SIを意味する記号がエディター上に付与されてしまっていたり、EBCDICではないファイルでも全て日本語の前後にSO/SIマークが付与されてしまうなどの事象が確認されています。(これらは基本的にはエディターの表示上の不備のため、z/OS側に持って行ってコンパイルする分には特に影響はないはずです。)

ちなみに、文字コード変換が入るということは、ソース中に含まれるのは"文字情報のみ"であることが前提であり、制御コードなど文字情報として扱えないデータが含まれているとコード変換が正しく行えず、エディターでの表示が行えなかったり、意図しない文字化けが生じることになります。

例えば、PCOMでは以下のようにx'0E', x'0F'のような制御コードのみをバイナリで指定したソースを編集することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/14cc792c-1d79-f924-cebd-70067d4a4e65.png)

このソースをVS Codeで開こうとすると、以下のようなエラーで開くことができませんのでご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d9b754e3-4724-f241-ee22-0e04a6d4ae8b.png)

### ファイル編集の競合
z/OS上のPDSメンバーをVS CodeのZowe Explorer経由で開いて編集している間は、当該メンバーへのロックは確保されていません。内部的にはREST APIでダウンロードしたファイルをPC上で編集し、保存する際にREST APIでアップロードするという操作が行われるためです。
つまり、VS Codeでソースを編集している間に、別のユーザーが同じファイルを編集してしまう可能性があります。その時の挙動を確認しておきます。

以下の操作を行ってみます。
1. VS Code上で、あるPDSメンバーを開いて編集 (まだ保存はしない)
2. VS Codeでの編集中に、同じPDSメンバーをPCOMで開いて編集し、保存する
3. VS Codeで編集中の同メンバーを保存する

3で編集した内容を保存しようとすると、この間に同ファイルに変更が入ったことを検知して以下のようなアラートを挙げてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f90e57e3-66e8-dc62-d560-de65850267c8.png)
Overwriteを選択すると、裏で変更された内容を今回の変更内容で上書きします。
Compareを選択すると、差分を比較できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/5e615955-7d51-13b8-ce35-f512c2daa974.png)
このように、並行して変更された内容と現在のファイルの差分が比較できますので、必要に応じて追加修正するなど判断することができます。

## USSファイル編集
MVSデータセット(PDSメンバーなど)のソースは、基本的にEBCDICの文字コード(IBM-930/IBM-939など)で保持されています。
一方、Unix System Service上のファイルは、デフォルトではEBCDICで扱われるものの、ファイルごとにUTF-8やISO8859-1(Asciiベース)の文字コードで保持され、ファイルごとにどの文字コードかを示す属性も保持しています。

参考:
[文字コード/タグ付け](https://qiita.com/tomotagwork/items/1d9c693352d6f0ee3c88#%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89%E3%82%BF%E3%82%B0%E4%BB%98%E3%81%91)

VS CodeでUSS上のファイルを開く場合、当該USSファイルにタグ付けされた文字コード情報に従って扱われます。つまり、IBM-1047とタグ付けされたファイルであればIBM-1047として、UTF-8とタグ付けされたファイルであればUTF-8としてコード変換有無も含め適切にハンドリングされます。タグ付けされていないファイル(Untagged)については、MVSデータセットの場合と同様、z/OSMFプロファイルのencoding指定に従ってハンドリングされます。
ちなみにVS CodeからUSSファイルを新規に作成する場合はUntagged(タグ付けなし)の状態となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/06247f7b-365c-0096-379a-2f7223c57a82.png)

## JES関連操作

Zowe ExplorerからJCLをエディターで開いて右クリック-[JCLとして提出]を選択します。
※日本語訳がおかしいですが、Submit as JCLの意味です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/aae7a9ab-3ed7-8158-cdfe-d73870443439.png)

以下のポップアップが出るので[Submit]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/87255661-4818-0f16-3d05-f294afafdbec.png)

すると、JCLがSubmitされ、右下に以下のようなメッセージが出力され、JOBIDがアサインされたことが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ee1895ba-165f-216f-4dfc-0d671e028e2a.png)

このJOBIDはハイパーリンクになっているので、これをクリックすると、JOBLOGを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/397dd1b7-9178-ca2e-c6d7-350a47cb999d.png)

フィルター(ユーザー、Prefix、Status)を指定して他のJOBLOGを検索して参照することも可能です。

※JOBLOG参照時に文字コード指定をする箇所は無さそうなので残念ながら日本語文字列部分は文字化けしてしまいます。

## MVSコマンド実行
ZOWE EXPLORER viewにて、MVSコマンドを実行したいz/OSに対するプロファイルを右クリックし、「MVSコマンドの発行」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/2810ab00-7280-63e2-79dc-1218420b6014.png)

プロンプトが開くので、ここにMVSコマンドを入力してEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ade77635-4372-1f6c-6c2b-dd107ae69512.png)

MVSコマンド実行結果が出力viewに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/f4b76ed8-15ac-a418-deb7-0312e4e01b29.png)

## TSOコマンド実行
ZOWE EXPLORER viewにて、MVSコマンドを実行したいz/OSに対するプロファイルを右クリックし、「TSOコマンドの発行」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d997e854-e06e-09df-b9af-9f132d7445e6.png)

まずAccount Numberを聞かれるので入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d98cac24-1626-0b74-6f7e-04103d695756.png)

プロンプトが開くので、ここにTSOコマンドを入力してEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b1a4408d-c9c0-6b9c-d8d6-c32767fa219a.png)

TSOコマンド実行結果が出力viewに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/98032850-ee0d-92a6-be41-45bc7bfe9122.png)