idea插件开发-自定义语言4-Syntax Highlighter

news2024/9/28 13:26:45

        SyntaxHighlighter用于指定应如何突出显示特定范围的文本,ColorSettingPage可以定义颜色。

一、Syntax Highter

1、文本属性键

        TextAttributesKey用于指定应如何突出显示特定范围的文本。不同类型的数据比如关键字、数字、字符串等如果要突出显示都需要创建一个TextAttributesKey实例。一个类型如果拥有多个TextAttributesKey突出显示时可以分层——例如,一个键可以定义类型的粗体和另一种颜色。

2、颜色设置

        EditorColorsScheme用来定义一个编辑器要使用哪些TextAttributesKey。这些是可以通过Settings | Editor | Color Scheme 来设置的。可通过com.intellij.colorSettingsPage进行扩展。

    另外 File | Export | Files or Selection to HTML 也采用了同样的配色方案。颜色设置可以参考示例:

final class PropertiesColorsPage implements ColorSettingsPage {
  private static final AttributesDescriptor[] ATTRS;

  static {
    ATTRS = Arrays.stream(PropertiesComponent.values())
      .map(component -> new AttributesDescriptor(component.getMessagePointer(), component.getTextAttributesKey()))
      .toArray(AttributesDescriptor[]::new)
    ;
  }

  @Override
  @NotNull
  public String getDisplayName() {
    return OptionsBundle.message("properties.options.display.name");
  }

  @Override
  public Icon getIcon() {
    return AllIcons.FileTypes.Properties;
  }

  @Override
  public AttributesDescriptor @NotNull [] getAttributeDescriptors() {
    return ATTRS;
  }

  @Override
  public ColorDescriptor @NotNull [] getColorDescriptors() {
    return ColorDescriptor.EMPTY_ARRAY;
  }

  @Override
  @NotNull
  public SyntaxHighlighter getHighlighter() {
    return new PropertiesHighlighter();
  }

  @Override
  @NotNull
  public String getDemoText() {
    return """
      # This comment starts with '#'
      greetings=Hello
      ! This comment starts with '!'
      what\\=to\\=greet : \\'W\\o\\rld\\',\\tUniverse\\n\\uXXXX
      """
      ;
  }

  @Override
  public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
    return null;
  }
}

3、词法分析器

        SyntaxHighlighter提供了第一级的语法高亮级别功能,语法高亮器返回TextAttributesKey每个标记类型的实例都可以特别高亮显示。可参考示例:

public class PropertiesHighlighter extends SyntaxHighlighterBase {
  @Override
  @NotNull
  public Lexer getHighlightingLexer() {
    return new PropertiesHighlightingLexer();
  }

  @Override
  public TextAttributesKey @NotNull [] getTokenHighlights(IElementType tokenType) {
    final PropertiesComponent type = PropertiesComponent.getByTokenType(tokenType);

    TextAttributesKey key = null;
    if (type != null) {
      key = type.getTextAttributesKey();
    }

    return SyntaxHighlighterBase.pack(key);
  }

  public enum PropertiesComponent {
    PROPERTY_KEY(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.KEY", DefaultLanguageHighlighterColors.KEYWORD),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.property.key"),
      PropertiesTokenTypes.KEY_CHARACTERS
    ),
    PROPERTY_VALUE(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.VALUE", DefaultLanguageHighlighterColors.STRING),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.property.value"),
      PropertiesTokenTypes.VALUE_CHARACTERS
    ),
    PROPERTY_COMMENT(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.LINE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.comment"),
      PropertiesTokenTypes.END_OF_LINE_COMMENT
    ),
    PROPERTY_KEY_VALUE_SEPARATOR(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.KEY_VALUE_SEPARATOR", DefaultLanguageHighlighterColors.OPERATION_SIGN),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.key.value.separator"),
      PropertiesTokenTypes.KEY_VALUE_SEPARATOR
    ),
    PROPERTIES_VALID_STRING_ESCAPE(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.VALID_STRING_ESCAPE", DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.valid.string.escape"),
      StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN
    ),
    PROPERTIES_INVALID_STRING_ESCAPE(
      TextAttributesKey.createTextAttributesKey("PROPERTIES.INVALID_STRING_ESCAPE", DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE),
      PropertiesBundle.messagePointer("options.properties.attribute.descriptor.invalid.string.escape"),
      StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN
    );

    private static final Map<IElementType, PropertiesComponent> elementTypeToComponent;
    private static final Map<TextAttributesKey, PropertiesComponent> textAttributeKeyToComponent;

    static {
      elementTypeToComponent = Arrays.stream(values())
        .collect(Collectors.toMap(PropertiesComponent::getTokenType, Function.identity()));

      textAttributeKeyToComponent = Arrays.stream(values())
        .collect(Collectors.toMap(PropertiesComponent::getTextAttributesKey, Function.identity()));
    }

    private final TextAttributesKey myTextAttributesKey;
    private final Supplier<@Nls String> myMessagePointer;
    private final IElementType myTokenType;

    PropertiesComponent(TextAttributesKey textAttributesKey, Supplier<@Nls String> messagePointer, IElementType tokenType) {
      myTextAttributesKey = textAttributesKey;
      myMessagePointer = messagePointer;
      myTokenType = tokenType;
    }

    public TextAttributesKey getTextAttributesKey() {
      return myTextAttributesKey;
    }

    Supplier<@Nls String> getMessagePointer() {
      return myMessagePointer;
    }

    IElementType getTokenType() {
      return myTokenType;
    }

    static PropertiesComponent getByTokenType(IElementType tokenType) {
      return elementTypeToComponent.get(tokenType);
    }

    static PropertiesComponent getByTextAttribute(TextAttributesKey textAttributesKey) {
      return textAttributeKeyToComponent.get(textAttributesKey);
    }

    static @Nls String getDisplayName(TextAttributesKey key) {
      final PropertiesComponent component = getByTextAttribute(key);
      if (component == null) return null;
      return component.getMessagePointer().get();
    }

    static @Nls HighlightSeverity getSeverity(TextAttributesKey key) {
      final PropertiesComponent component = getByTextAttribute(key);
      return component == PROPERTIES_INVALID_STRING_ESCAPE
             ? HighlightSeverity.WARNING
             : null;
    }
  }

}

语义高亮

        语义突出显示其实是提供了一个额外的着色层,以改善几个相关项(例如,方法参数、局部变量)的视觉区分。可实现com.intellij.highlightVisitor扩展点,这里的颜色设置要实现RainbowColorSettingsPage接口。

4、解析器

        第二级错误突出显示发生在解析期间。如果根据语言的语法,特定的标记序列是无效的,则PsiBuilder.error()方法可以突出显示无效标记并显示一条错误消息,说明它们无效的原因。

5、注释器

        第三层高亮是通过Annotator接口实现。一个插件可以在扩展点中注册一个或多个注释器com.intellij.annotator,这些注释器在后台高亮过程中被调用,以处理自定义语言的 PSI 树中的元素。属性language应设置为此注释器适用的语言 ID。

        注释器不仅可以分析语法,还可以用于 PSI 分析语义,因此可以提供更复杂的语法和错误突出显示逻辑。注释器还可以为其检测到的问题提供快速修复。文件更改时,将增量调用注释器以仅处理 PSI 树中更改的元素。

错误/警告

        大体的代码实现如下:

holder.newAnnotation(HighlightSeverity.WARNING,"Invalid code") // or HighlightSeverity.ERROR
    .withFix(new MyFix(psiElement))
    .create();

句法

        大体的代码实现如下:

holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
    .range(rangeToHighlight)
    .textAttributes(MyHighlighter.EXTRA_HIGHLIGHT_ATTRIBUTE)
    .create();
        完整的示例可参考:
public class PropertiesAnnotator implements Annotator {
  private static final ExtensionPointName<DuplicatePropertyKeyAnnotationSuppressor>
    EP_NAME = ExtensionPointName.create("com.intellij.properties.duplicatePropertyKeyAnnotationSuppressor");

  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!(element instanceof Property property)) return;
    PropertiesFile propertiesFile = property.getPropertiesFile();
    final String key = property.getUnescapedKey();
    if (key == null) return;
    Collection<IProperty> others = propertiesFile.findPropertiesByKey(key);
    ASTNode keyNode = ((PropertyImpl)property).getKeyNode();
    if (keyNode == null) return;
    if (others.size() != 1 &&
      EP_NAME.findFirstSafe(suppressor -> suppressor.suppressAnnotationFor(property)) == null) {
      holder.newAnnotation(HighlightSeverity.ERROR,PropertiesBundle.message("duplicate.property.key.error.message")).range(keyNode)
      .withFix(PropertiesQuickFixFactory.getInstance().createRemovePropertyFix(property)).create();
    }

    highlightTokens(property, keyNode, holder, new PropertiesHighlighter());
    ASTNode valueNode = ((PropertyImpl)property).getValueNode();
    if (valueNode != null) {
      highlightTokens(property, valueNode, holder, new PropertiesValueHighlighter());
    }
  }

  private static void highlightTokens(final Property property, final ASTNode node, final AnnotationHolder holder, PropertiesHighlighter highlighter) {
    Lexer lexer = highlighter.getHighlightingLexer();
    final String s = node.getText();
    lexer.start(s);

    while (lexer.getTokenType() != null) {
      IElementType elementType = lexer.getTokenType();
      TextAttributesKey[] keys = highlighter.getTokenHighlights(elementType);
      for (TextAttributesKey key : keys) {
        final String displayName = PropertiesComponent.getDisplayName(key);
        final HighlightSeverity severity = PropertiesComponent.getSeverity(key);
        if (severity != null && displayName != null) {
          int start = lexer.getTokenStart() + node.getTextRange().getStartOffset();
          int end = lexer.getTokenEnd() + node.getTextRange().getStartOffset();
          TextRange textRange = new TextRange(start, end);
          TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key);
          AnnotationBuilder builder = holder.newAnnotation(severity, displayName).range(textRange).enforcedTextAttributes(attributes);

          int startOffset = textRange.getStartOffset();
          if (key == PropertiesComponent.PROPERTIES_INVALID_STRING_ESCAPE.getTextAttributesKey()) {
            builder = builder.withFix(new IntentionAction() {
              @Override
              @NotNull
              public String getText() {
                return PropertiesBundle.message("unescape");
              }

              @Override
              @NotNull
              public String getFamilyName() {
                return getText();
              }

              @Override
              public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
                if (!BaseIntentionAction.canModify(file)) return false;

                String text = file.getText();
                return text.length() > startOffset && text.charAt(startOffset) == '\\';
              }

              @Override
              public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
                if (file.getText().charAt(startOffset) == '\\') {
                  editor.getDocument().deleteString(startOffset, startOffset + 1);
                }
              }

              @Override
              public boolean startInWriteAction() {
                return true;
              }
            });
          }
          builder.create();
        }
      }
      lexer.advance();
    }
  }
}

二、示例

1、定义SyntaxHighlighterFactory

public class SimpleSyntaxHighlighter extends SyntaxHighlighterBase {

  public static final TextAttributesKey SEPARATOR =
          createTextAttributesKey("SIMPLE_SEPARATOR", DefaultLanguageHighlighterColors.OPERATION_SIGN);
  public static final TextAttributesKey KEY =
          createTextAttributesKey("SIMPLE_KEY", DefaultLanguageHighlighterColors.KEYWORD);
  public static final TextAttributesKey VALUE =
          createTextAttributesKey("SIMPLE_VALUE", DefaultLanguageHighlighterColors.STRING);
  public static final TextAttributesKey COMMENT =
          createTextAttributesKey("SIMPLE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT);
  public static final TextAttributesKey BAD_CHARACTER =
          createTextAttributesKey("SIMPLE_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER);


  private static final TextAttributesKey[] BAD_CHAR_KEYS = new TextAttributesKey[]{BAD_CHARACTER};
  private static final TextAttributesKey[] SEPARATOR_KEYS = new TextAttributesKey[]{SEPARATOR};
  private static final TextAttributesKey[] KEY_KEYS = new TextAttributesKey[]{KEY};
  private static final TextAttributesKey[] VALUE_KEYS = new TextAttributesKey[]{VALUE};
  private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{COMMENT};
  private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];

  @NotNull
  @Override
  public Lexer getHighlightingLexer() {
    return new SimpleLexerAdapter();
  }

  @Override
  public TextAttributesKey @NotNull [] getTokenHighlights(IElementType tokenType) {
    if (tokenType.equals(SimpleTypes.SEPARATOR)) {
      return SEPARATOR_KEYS;
    }
    if (tokenType.equals(SimpleTypes.KEY)) {
      return KEY_KEYS;
    }
    if (tokenType.equals(SimpleTypes.VALUE)) {
      return VALUE_KEYS;
    }
    if (tokenType.equals(SimpleTypes.COMMENT)) {
      return COMMENT_KEYS;
    }
    if (tokenType.equals(TokenType.BAD_CHARACTER)) {
      return BAD_CHAR_KEYS;
    }
    return EMPTY_KEYS;
  }

}
<extensions defaultExtensionNs="com.intellij">
  <lang.syntaxHighlighterFactory
      language="Simple"
      implementationClass="org.intellij.sdk.language.SimpleSyntaxHighlighterFactory"/>
</extensions>

2、定义颜色设置界面

public class SimpleColorSettingsPage implements ColorSettingsPage {

  private static final AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[]{
          new AttributesDescriptor("Key", SimpleSyntaxHighlighter.KEY),
          new AttributesDescriptor("Separator", SimpleSyntaxHighlighter.SEPARATOR),
          new AttributesDescriptor("Value", SimpleSyntaxHighlighter.VALUE),
          new AttributesDescriptor("Bad value", SimpleSyntaxHighlighter.BAD_CHARACTER)
  };

  @Nullable
  @Override
  public Icon getIcon() {
    return SimpleIcons.FILE;
  }

  @NotNull
  @Override
  public SyntaxHighlighter getHighlighter() {
    return new SimpleSyntaxHighlighter();
  }

  @NotNull
  @Override
  public String getDemoText() {
    return "# You are reading the \".properties\" entry.\n" +
            "! The exclamation mark can also mark text as comments.\n" +
            "website = https://en.wikipedia.org/\n" +
            "language = English\n" +
            "# The backslash below tells the application to continue reading\n" +
            "# the value onto the next line.\n" +
            "message = Welcome to \\\n" +
            "          Wikipedia!\n" +
            "# Add spaces to the key\n" +
            "key\\ with\\ spaces = This is the value that could be looked up with the key \"key with spaces\".\n" +
            "# Unicode\n" +
            "tab : \\u0009";
  }

  @Nullable
  @Override
  public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMap() {
    return null;
  }

  @Override
  public AttributesDescriptor @NotNull [] getAttributeDescriptors() {
    return DESCRIPTORS;
  }

  @Override
  public ColorDescriptor @NotNull [] getColorDescriptors() {
    return ColorDescriptor.EMPTY_ARRAY;
  }

  @NotNull
  @Override
  public String getDisplayName() {
    return "Simple";
  }

}

支持通过用 分隔节点来对运算符或大括号等相关属性进行分组//,例如:

AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[] {
    new AttributesDescriptor("Operators//Plus", MySyntaxHighlighter.PLUS),
    new AttributesDescriptor("Operators//Minus", MySyntaxHighlighter.MINUS),
    new AttributesDescriptor("Operators//Advanced//Sigma", MySyntaxHighlighter.SIGMA),
    new AttributesDescriptor("Operators//Advanced//Pi", MySyntaxHighlighter.PI),
    //...
};
<extensions defaultExtensionNs="com.intellij">
  <colorSettingsPage
      implementation="org.intellij.sdk.language.SimpleColorSettingsPage"/>
</extensions>

3、测试运行

        颜色配置页面可从Settings | Editor | Color Scheme | Simple查看。如下图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/808764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ReID网络(一):MGN网络

Start MGN 1. 序言 现代基于感知的信息中&#xff0c;视觉信息占了80~85%。基于视觉信息的处理和分析被应用到诸如安防、电力、汽车等领域。 以安防市场为例&#xff0c;早在2017年&#xff0c;行业咨询公司IHS Market&#xff0c;我国在公共和私人领域安装有摄像头约1.76亿…

《TCP IP网络编程》第十三章

第 13 章 多种 I/O 函数 13.1 send & recv 函数 Linux 中的 send & recv&#xff1a; send 函数定义&#xff1a; #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags); /* 成功时返回发送的字节数&#xff0c;失败…

36.悬浮板

悬浮板 html部分 <div class"container"><div class"square"></div> </div>css部分 *{margin: 0;padding: 0; } body{background-color: #111;height: 100vh;overflow: hidden;display: flex;justify-content: center;align-it…

layui框架学习(33:流加载模块)

Layui中的流加载模块flow主要支持信息流加载和图片懒加载两部分内容&#xff0c;前者是指动态加载后续内容&#xff0c;示例的话可以参考csdn个人博客主页&#xff0c;鼠标移动到页面底部时自动加载更多内容&#xff0c;而后者是指页面显示图片时才会延迟加载图片信息。   fl…

苍穹外卖-day08

苍穹外卖-day08 本项目学自黑马程序员的《苍穹外卖》项目&#xff0c;是瑞吉外卖的Plus版本 功能更多&#xff0c;更加丰富。 结合资料&#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…

第17节 R语言分析:生物统计数据集 R 编码分析和绘图

生物统计数据集 R 编码分析和绘图 生物统计学,用于对给定文件 data.csv 中的医疗数据应用 R 编码,该文件是患者人口统计数据集,包含有关来自各种祖先谱系的个体的标准信息。 数据集特征解释 脚本 output= file("Output.txt") # File name of output log sink(o…

[数据集][目标检测]城市道路井盖破损丢失目标检测1377张

数据集制作单位&#xff1a;未来自主研究中心(FIRC) 数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1377 标注数量(xml文件个数)&#xff1a;1377 标注类别数&a…

Spring源码(五)— 解析XML配置文件(二) 定制化标签解析流程

上一篇以bean标签为例&#xff0c;介绍了属于defaultNamesapce标签的解析流程&#xff0c;但是defaultNamespace中默认的标签只有bean、beans、alias、import这四个&#xff0c;而我们平时在xml中配置的标签有很多。那其余的标签是如何解析&#xff1f; 在这篇文章会详细介绍定…

一个监控系统的典型架构

监控系统的典型架构图&#xff0c;从左往右看&#xff0c;采集器是负责采集监控数据的&#xff0c;采集到数据之后传输给服务端&#xff0c;通常是直接写入时序库。然后就是对时序库的数据进行分析和可视化&#xff0c;分析部分最典型的就是告警规则判断&#xff0c;即图上的告…

【李宏毅机器学习·学习笔记】Deep Learning General Guidance

本节课可视为机器学习系列课程的一个前期攻略&#xff0c;这节课主要对Machine Learning 的框架进行了简单的介绍&#xff1b;并以training data上的loss大小为切入点&#xff0c;介绍了几种常见的在模型训练的过程中容易出现的情况。 课程视频&#xff1a; Youtube&#xff1…

【Spring框架】SpringBoot配置文件

目录 配置文件作用application.properties中午乱码问题&#xff1a;配置文件里面的配置类型分类SpringBoot热部署properties基本语法properties配置文件的优缺点&#xff1a;yml配置文件说明yml基本语法配置对象properties VS yml 配置文件作用 整个项⽬中所有重要的数据都是在…

【MyBatis 学习二】增删改查 参数占位符 #{} 和 ${}的使用

目录 一、增删改查 &#x1f337;1、用户类 &#x1f337;2、UserMapper &#x1f337;3、UserMapper.xml &#x1f337;4、测试类Test &#x1f337;5、UserService类 &#x1f337;6、UserController类 &#x1f337;7、注意点总结 二、#{} 和${} 的使用区别 &…

一个 SpringBoot 项目能处理多少请求

首先&#xff0c;这个问题有坑&#xff0c;因为 spring boot 不处理请求&#xff0c;只是把现有的开源组件打包后进行了版本适配、预定义了一些开源组件的配置通过代码的方式进行自动装配进行简化开发。这是 spring boot 的价值。 如果我是面试官&#xff0c;我不会问这种问题。…

BLE基础理论/Android BLE开发示例

参考&#xff1a;https://blog.csdn.net/qq_36075612/article/details/127739150?spm1001.2014.3001.5502 参考&#xff1a; https://blog.csdn.net/qq_36075612/article/details/122772966?spm1001.2014.3001.5502 目录 蓝牙的分类传统蓝牙低功耗蓝牙 蓝牙专业词汇&#xff…

深度剖析C++ 异常机制

传统排错 我们早在 C 程序里面传统的错误处理手段有&#xff1a; 终止程序&#xff0c;如 assert&#xff1b;缺陷是用户难以接受&#xff0c;说白了就是一种及其粗暴的手法&#xff0c;比如发生内存错误&#xff0c;除0错误时就会终止程序。 返回错误码。缺陷是需要我们自己…

docker启动容器报错

报错信息 [rootDream soft]# docker run -it -d -p 8080:8080 tomcat eec9fab6b9ca06d2bbf1467aef05d8020ee60448978e10ac20c38888934f0a0b docker: Error response from daemon: driver failed programming external connectivity on endpoint hungry_euclid (163242f0079e72…

C语言之pthread_cond_t信号变化探究总结(八十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

MySQL | 常用命令示例

MySQL | 常用命令示例 一、启停MySQL数据库服务二、连接MySQL数据库三、创建和管理数据库四、创建和管理数据表五、数据备份和恢复六、查询与优化 MySQL是一款常用的关系型数据库管理系统&#xff0c;广泛应用于各个领域。在使用MySQL时&#xff0c;我们经常需要编写一些常用脚…

M 芯片的 macos 系统安装虚拟机 centos7 网络配置

centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了&#xff0c;如果重启网卡不管用&#xff0c;则重启虚拟机即可 “ ifcfg-ens160 ” 这…

盖子的c++小课堂——第二十一讲:map

前言 时隔一周&#xff0c;我又来更新了^_^&#xff0c;今天都第二十一讲了&#xff0c;前三个板块马上就结束了&#xff0c;也就是小课堂&#xff08;1&#xff09;马上结束了&#xff0c;敬请期待“盖子的c小课堂&#xff08;2&#xff09;”&#xff0c;嘿嘿~~ map 数据容…