整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Rust学习笔记(四十四)Cargo发布crate和工作空间(Workspace)

用pub use导出方便使用的公共API

问题:crate的程序结构在开发时对于开发者很合理,但是对它的使用者不够方便。例如:开发者会把程序结构分为很多层,使用者想找到这种深层结构中的某个类型费时费力。例: 有这么一个类型,开发者这样定义my_crate::some_module::another_module::UsefulType,用户用的时候希望是my_crate::UsefulType 解决方法:

  • 不需要重新组织内部代码的结构
  • 使用pub use可以重新导出,创建一个与内部私有结构不同的对外公共结构

例:

// src/lib.rs
//! # Art
//!
//! A library for modeling artistic concepts.

pub mod kinds {
    /// The primary colors according to the RYB color model.
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }

    /// The secondary colors according to the RYB color model.
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;

    /// Combines two primary colors in equal amounts to create
    /// a secondary color.
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        SecondaryColor::Green
    }
}
// src/main.rs
use art::kinds::PrimaryColor;
use art::utils::mix;

fn main() {
    let red = PrimaryColor::Red;
    let yellow = PrimaryColor::Yellow;
    mix(red, yellow);
}

可以看到,PrimaryColor和mix分别在不同的模块里。使用起来不是很友好。使用cargo doc --open生成并查看文档:

文档看起来也比较麻烦,需要点kinds和utils才能查看里的内容。

下面利用pub use进行修改

// src/lib.rs
//! # Art
//!
//! A library for modeling artistic concepts.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

pub mod kinds {
    /// The primary colors according to the RYB color model.
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }

    /// The secondary colors according to the RYB color model.
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;

    /// Combines two primary colors in equal amounts to create
    /// a secondary color.
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        SecondaryColor::Green
    }
}
// src/main.rs
use art::PrimaryColor;
use art::mix;

fn main() {
    let red = PrimaryColor::Red;
    let yellow = PrimaryColor::Yellow;
    mix(red, yellow);
}

查看文档:

可以看到,使用和查看文档都比较方便。

创建并设置crates.io账号

发布crate前,需要在crates.io创建账号并获得API token。

  • 首先进入crates.io,点击右上角的Log in with Github。
  • 登陆后进入账号设置页面,新建一个API token
  • 运行cargo login 自己的API token命令,会将API token存储在本地~/.cargo/credentials
  • 如果token被泄露,可以去创建token的地方将其删除,防止别人冒用。
  • 绑定自己的邮箱,否则无法发布

在Cargo.toml文件里填写一些信息:

[package]
name = "art"#必须是在crates.io里唯一的
description = "a demo for publish crate."#简介,会出现在crate搜索数据中
license = "MIT"#提供开源许可标识,可在http://spdx.org/licenses/查看,可以指定多个,用OR隔开
version = "0.1.0"#版本号
author = "demo"#作者
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

使用cargo publish发布。 crate一旦发布,就是永久性的:该版本无法覆盖,代码无法删除。目的是让依赖该版本的项目可以一直使用。如果想发布新版本,只需要修改Cargo.toml中的version,然后重新发布即可。版本语义参考http://semver.org/

使用cargo yank从crates.io撤回版本

我们不可以删除crate之前的版本,但是可以使用cargo yank防止其他项目把它作为新的依赖,换句话说就是防止新的项目依赖该版本。已经存在的项目可继续将其作为依赖(并可下载)。 yank意味着:

  • 所有已经产生Cargo.lock文件的项目都不会中断
  • 但是任何将来生成的Cargo.lock文件都不会使用已经yank的版本

撤回命令:cargo yank --vers 1.0.1 取消撤回:cargo yank --vers 1.0.1 --undo

Cargo工作空间

Cargo工作空间:帮助管理多个相互关联且需要协同开发的crate,它是一套共享同一个Cargo.lock和输出文件夹(target)的包。

创建工作空间

有多种方式创建工作空间,例如创建含有1个二进制crate和2个library(库) crate的工作空间:

  • 二进制crate中main函数依赖于其它两个library
  • 其中一个库crate提供add_one函数
  • 另一个库提供add_two函数

首先创建一个空文件夹,然后在里面新建Cargo.toml文件:

[workspace]

members = [
    "adder",
    "add-one",
    "add-two",
]

然后分别执行cargo new adder,cargo new add-one --lib,cargo new add-two --lib来创建一个二进制crate和两个库crate。

//add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
    x + 1
}
//add-two/src/lib.rs
pub fn add_two(x: i32) -> i32 {
    x + 2
}
//adder/src/main.rs
use add_one;
use add_two;
fn main() {
    let num = 10;

    println!(
        "Hello, world! {} + 1 = {} {} + 2 = {}",
        num,
        add_one::add_one(num),
        num,
        add_two::add_two(num),
    );
}

}

使用cargo run -p adder运行workspace中的二进制crate,同理,cargo test命令也可以用-p指定要运行哪个crate的测试。

在工作空间中依赖外部crate

工作空间只有一个Cargo.lock文件,在工作空间顶层目录。它能保证工作空间内所有crate使用的依赖版本都相同。例如我们在Cargo.toml 和 add-one/Cargo.toml 中都增加 rand crate,则 Cargo 会将其都解析为同一版本并记录到唯一的 Cargo.lock 中。使得工作空间中的所有 crate 都使用相同的依赖意味着其中的 crate 都是相互兼容的。例:

#adder/Cargo.toml
[package]
name = "adder"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
add-one = {path = "../add-one"}
add-two = {path = "../add-two"}
rand = "0.3.14"
#add-one/Cargo.toml
[package]
name = "add-one"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.3.13"

adder和add_one的Cargo.toml分别填写依赖rand的0.3.14和0.3.13,可以从下面看出我这里Cargo.lock文件里这两个工crate的依赖都被解析到了0.3.23这同一个版本上。

# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "add-one"
version = "0.1.0"
dependencies = [
 "rand 0.3.23",
]

[[package]]
name = "add-two"
version = "0.1.0"

[[package]]
name = "adder"
version = "0.1.0"
dependencies = [
 "add-one",
 "add-two",
 "rand 0.3.23",
]

如果你选择向 crates.io发布工作空间中的 crate,每一个工作空间中的 crate 需要单独发布。cargo publish 命令并没有 --all 或者 -p 参数,所以必须进入每一个 crate 的目录并运行 cargo publish 来发布工作空间中的每一个 crate。

从crates.io安装二进制crate

命令:cargo install 来源:https://crates.io 限制:只能安装具有二进制目标(binary target)的crate 二进制目标:是一个可运行程序,由src/main.rs或其它被指定为二进制文件的crate生成。 通常README里有关于crate的描述:

  • 是否拥有库目标(library target)
  • 是否拥有二进制目标(binary target)
  • 拥有二者

cargo install安装的二进制文件存放在根目录的bin文件夹。如果你是用rustup安装的Rust,没有任何自定义配置,那么二进制存放的目录是HOME/.cargo/bin,要确保该目录在环境变量HOME/.cargo/bin,要确保该目录在环境变量PATH中,不然安装的二进制文件无法直接运行。例:

> cargo install test_bin
    Updating `sjtu` index
  Downloaded test_bin v0.3.0 (registry `sjtu`)
  Downloaded 1 crate (7.3 KB) in 1.04s
  Installing test_bin v0.3.0
   Compiling test_bin v0.3.0
    Finished release [optimized] target(s) in 2.05s
  Installing C:\Users\Chris\.cargo\bin\test_bin.exe
   Installed package `test_bin v0.3.0` (executable `test_bin.exe`)
> test_bin
Output from my CLI app!

我们安装了test_bin这个binary crate,然后就可以直接用test_bin来运行这个可执行程序。

使用自定义命令扩展cargo

cargo被设计成可以使用子命令来扩展,并且无需修改cargo本身。例如$PATH中的某个二进制是cargo-something,那么我们就可以像子命令一样运行它:cargo something,这样看起来something像cargo的子命令一样。 而且这样的自定义命令可以通过cargo --list列出来。 优点:可使用cargo install来安装扩展,像内置工具一样来运行。

. 自定义积木

虽然Blockly定义了许多标准积木,但大多数应用程序需要定义和实现至少一些域相关积木,这也是Scartch3.0 Blocks使用Blockly的原因,可扩展性强。积木由三个部分组成:积木定义对象:定义积木的外观和行为,包括文本,颜色,字段和连接。添加积木到Toolbox:工具箱XML中对积木类型的引用,因此用户可以将其添加到工作区。添加积木代码:生成此积木的代码字符串。它是用JavaScript编写的,即使目标语言不是JavaScript,甚至是用于Android端的Blockly。

积木定义

用于Web加载的Blockly通过脚本文件加载积木。在“blocks/”目录中包含几个标准积木的示例。假设您的积木不适合现有分类,需要创建一个新的JavaScript文件。这个新的JavaScript文件需要包含在编辑器HTML文件的script标签列表中。

注意:大多数积木都可以使用Blockly Developer Tools定义,而不是手动创建下面的代码。

典型的积木定义如下所示,Json语言版本:

Blockly.Blocks['string_length'] = {
  init: function() {
    this.jsonInit({
      "message0": 'length of %1',
      "args0": [
        {
          "type": "input_value",
          "name": "VALUE",
          "check": "String"
        }
      ],
      "output": "Number",
      "colour": 160,
      "tooltip": "Returns number of letters in the provided text.",
      "helpUrl": "http://www.w3schools.com/jsref/jsref_length_string.asp"
    });
  }
};

此处添加了一个名为VALUE的的积木,输入一个字符串(String)参数,输出为数字(Number),积木显示内容为length of。

将积木添加到Toolbox

定义后,使用类型名称将积木引用到工具箱:

<xml id="toolbox" style="display: none">
    <category name="Text">
        <block type="string_length"></block>
    </category>
...
</xml>

添加积木对应的代码

最后,要将积木转换为代码,请将积木与生成器函数配对。每个积木都对应有生成器函数,多个积木形成积木组,多个生成器函数,形成代码片段,片段就可以执行。生成器特定于所需的输出语言,但标准生成器通常采用以下格式:

Blockly.JavaScript['text_length'] = function(block) {
// String or array length.
    var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
    Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\'';
    return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER];
}

Blockly可以将积木导出为许多编程语言,包括这些流行的选项:JavaScript、Python、PHP、Lua、Dart

4. Events

工作区上的每个更改都会触发一个事件。这些事件完整地描述了每个变化的前后状态。

监听事件

工作区具有可用于侦听事件流的addChangeListener方法和removeChangeListener方法。以下示例检测用户何时创建其第一条评论,然后停止监听。

function onFirstComment(event) {
  if (event.type == Blockly.Events.CHANGE &&
      event.element == 'comment' &&
      !event.oldValue && event.newValue) {
    alert('Congratulations on creating your first comment!')
    workspace.removeChangeListener(onFirstComment);
  }
}
workspace.addChangeListener(onFirstComment);

积木也可以定义onchange函数,只要积木的工作空间发生更改,就会调用该函数。

事件类型

名称类型描述type串积木事件、变量事件workspaceId串作区的UUID。可以找到工作区Blockly.Workspace.getById(event.workspaceId)blockId串积木的UUID。该积木可以找到workspace.getBlockById(event.blockId)group串组的UUID。某些事件是不可分割的组的一部分,例如在堆栈中插入语句

积木创建事件( Blockly.Events.BLOCK_CREATE)积木删除事件( Blockly.Events.BLOCK_DELETE)积木变更事件( Blockly.Events.BLOCK_DCHANGE)积木移动事件( Blockly.Events.BLOCK_MOVE)变量创建事件( Blockly.Events.VAR_CREATE)变量删除事件( Blockly.Events.VAR_DELETE)变量重命名事件(Blockly.Events.VAR_RENAME)UI事件(lockly.Events.UI):例如滚动,缩放,拖动气泡等事件。

5. 代码编辑器

生成代码

第一步是导入相关语言的生成器。 Blockly包括以下生成器:javascript_compressed.jspython_compressed.jsphp_compressed.jslua_compressed.jsdart_compressed.js应该在blockly_compressed.js之后包含代码生成器。例如,以下是包含的JavaScript生成器:

<script src="blockly_compressed.js"></script>
<script src="javascript_compressed.js"></script>

通过此调用,用户的块可以随时从您的应用程序导出到代码:var code = Blockly.JavaScript.workspaceToCode(workspace);在前面两行中用Python, PHP, Lua或Dart替换JavaScript以切换生成的语法。

实时生成

通过向Blockly的change事件添加一个监听器来实时生成和显示代码:

论在WebStorm 中做什么,都是在项目的上下文中执行的。WebStorm 中的项目是一个文件夹,其中包含您编辑的源代码、您使用的库和工具(例如,在node_modules子文件夹中)以及各种应用程序配置文件(例如,package.json或.eslintrc)。

WebStorm已更新至V2022.1,欢迎下载WebStorm最新版本试用:

点击获WebStorm官方正式版

在 WebStorm 中打开一个文件夹后,.idea子文件夹将添加到其中 WebStorm 存储其内部配置设置,例如项目代码样式或版本控制系统。

.idea目录中的所有设置文件都应置于版本控制之下,除了workspace.xml,它存储您的本地首选项。workspace.xml文件应被VCS标记为忽略。

WebStorm 不支持直接编辑远程主机上的文件。因此,要在 WebStorm 中使用远程源,需要下载它们,打开存储它们的文件夹,并将它们安排在 WebStorm 项目中,如从现有本地源创建项目中所述。要使本地和远程源保持同步,请使用“部署选项”对话框中的“将更改的文件自动上载到默认服务器”列表配置自动上载。

在项目之间切换

如果您同时打开了多个项目,您可以使用以下选项在它们之间切换:

  • 切换到下一个项目窗口:(Ctrl+Alt+]窗口|下一个项目窗口)
  • 切换到上一个项目窗口:(Ctrl+Alt+[窗口|上一个项目窗口)
  • 或者,打开窗口菜单并选择要切换到的项目。

重命名项目

  1. 右键单击项目的根文件夹并选择Refactor | 从上下文菜单重命名Shift+F6或按。
  2. 在打开的对话框中,选择重命名策略。
  3. 如果项目名称与其根文件夹的名称相同,请选择Rename directory。
  4. 如果项目名称与其根文件夹的名称不同,请选择Rename project。
    或者,选择文件 | 从主菜单重命名项目并在打开的对话框中输入项目的新名称。
    如果您的应用程序部署到远程服务器并且项目根文件夹映射到服务器根目录,也请选择此选项。
  5. 当然,您可以重命名根文件夹并相应地更新服务器配置中的映射。

将项目移动到另一个位置

  1. 在Project工具窗口Alt+1中,右键单击项目的根目录并选择Refactor | 移动目录( F6)。
  2. 在打开的对话框中,为项目指定一个新位置,然后单击Refactor。

更改项目的默认位置

在 WebStorm 中,您可以为项目指定默认父文件夹。当您打开项目时,WebStorm 将从该文件夹开始。每次创建新项目时也会建议使用此默认位置。

  1. 打开设置/首选项对话框 ( Ctrl+Alt+S) 并转到外观和行为 | 系统设置。
  2. 在默认目录字段中,指定要存储项目的文件夹的路径。
  3. 下次创建项目时,WebStorm 会建议指定目录作为新项目的父目录。

通过 VCS 共享项目设置

根据您的选择处理配置文件。修改项目设置并创建新的配置文件后,IDE 会在屏幕底部显示一条通知,提示您选择如何处理此项目中的配置文件:

  • 查看文件:查看已创建配置文件的列表并选择要置于版本控制之下的配置文件。之后,选定的文件将被安排添加到 VCS。
  • Always Add:静默计划在.idea目录中创建的所有配置文件以添加到 VCS(仅适用于当前项目)。
  • 不要再问:永远不要安排配置文件添加到 VCS;在您手动将它们添加到 VCS 之前,它们将具有未版本化状态(仅适用于当前项目)。

如果您在未选择任何选项的情况下关闭通知,则在创建新配置文件后它将再次出现。即使您重新启动 IDE,新文件也将进入该列表,直到您选择其中一个选项。

不可共享的配置文件列表

前端开发工具WebStorm 识别配置文件并将它们自动添加到忽略文件列表中。但是,如果您手动共享项目,我们建议您避免将这些文件和文件夹置于版本控制之下:

  • .idea/workspace.xml
  • .idea/usage.statistics.xml
  • .idea/字典文件夹
  • .idea/架子文件夹

将全局设置复制到项目级别

全局 (IDE) 设置与项目分开存储。这就是为什么这些设置不会通过版本控制与项目一起共享。

但是,可以将某些设置复制到项目级别。例如,您可以创建检查配置文件的副本,从代码完成和自动导入中排除的类和包的列表。如果这样做,IDE 会在.idea目录中创建相应的配置文件,您可以通过 VCS 与项目一起共享这些配置文件。

以上就是有关WebStorm项目的介绍,更多关于WebStorm价格信息可进入慧都官网查看。

WebStorm是一个针对JavaScript和相关技术的集成开发环境。像其他JetBrains IDE一样,它使你的开发体验更加愉快,使日常工作自动化,并帮助你轻松处理复杂的任务。