# 自定义智能提示

动态语言实现智能提示是非常困难的。aardio 虽然是动态语言，但创造了一种特独的注释指令用于配置库文件的智能提示。这些提示在代码中只是有特殊格式的注释，但是 aardio 开发环境可以自动识别这些注释并生成智能提示、代码自动完成、代码模板数据。

aardio 标准库也提供 ide.doc 库可以自动将这些库文件的智能提示配置转换为库参考文档。

请参考 

[命名空间](../language-reference/namespace.md) 

[库](import.md)

## **在注释中定义智能提示**

智能提示注释指令的基本结构：

```aardio
/*intellisense(命名空间.命名空间)
a = 提示文字
b.c = 提示文字，必须用\n表示换行
b.? = 对任意字段名配置的代码提示 
end intellisense*/
```  
  
智能提示是由一个或多个名值对组成的字符串列表。
- 名：指的是用户输入的代码或对象
- 值：指的是输入时显示的智能提示或代码模板
名值之间必须用等号分隔，优先查找第一个前后有空格的等号作为分隔符，如果没有找到，则会查找第一个出现的等号（不再要求前后空格）作为分隔符。

以换行分隔多个名值对。每个名值对都必须是单行的，如果智能提示包行多行必须以 "\n" 替代。

支持用问号匹配任意字段名称，例如：
  
```aardio
/*intellisense()*/
testa.?.c  = 可使用问号表示任意名字 
/*end intellisense*/
```  

那么输入 `testa.任意名字.` 都会提示上面的 c， 另在下标操作符中输入的任意成员名字都会匹配 `?` 号指定的智能刊示，例如  `testa["任意名字"].c` 会显示上面的智能提示。
  
如果等号后面的值(智能提示)的第一个字符是`@`则表示定义一个自动完成的模板代码，如果`@`后面紧跟一个圆点，则表示模板自动连接在用户输入的命名空间最后一个圆点之后，例如：  

`!time.format = @.format="%Y年%m月%d日 %H时%M分%S秒";`

等号前面的小圆点只能用作对象的成员操作符或分隔命名空间，如果有其他作用的圆点，例如 `...`,则必须用 `->`替换`.`表示为 `->->->`。例如:  

`!gdipgraphics.rotate(10, gdip->MatrixOrder->__ ) = 旋转画布 `

这是 gdip.graphics 库中配置的提示, `!gdipgraphics` 是动态创建的对象，括号后面是函数签名。  

在弹出提示或完成代码时,上面的`->`都会显示为圆点`.`,在圆点后面用两个下划线`__`指定输入完成后光标自动插入此位置（代码模板也支持用 `__` 指定光标插入位置）,  在用户完成该代码以后,立即会跳出进一步的代码提示,非常方便。


## 在智能提示中使用引用代码段

对于每一个智能提示定义的名值对，值部分的提示文字首字符不能是花括号`{`，如果值部分第一行的行尾以`{换行`结束，那么其值可以跨行直到`换行}`为止。即首行以`{`结束，尾行以`}`开始。注意换行符与大括号中间不要有其他字符或空白字符。

示例：
  
```aardio
/*intellisense(命名空间.命名空间)*/
a = 提示文字 {
             a=={}//如果大括号内侧不是换行符，不能表示提示段落的开始或结束。
} 
b = 提示文字 
/*end intellisense*/
```

这种语法的目的是让我们可以用多行的方式写智能提示，但前提是必须符合上面的要求。

## 命名空间重定向

  
```aardio
/*intellisense()
testio = io.
end intellisense*/
```  

在提示文字尾部加一个小圆点表示命名空间转向。  
`testio = io.` 表示输入`testio.`时自动显示`io.`的成员  
  
所以,如果不是确认要定义一个命名空间转向,  
普通智能提示的说明文字结束尽可能避免使用圆点或（可以使用句号），以避免被误以为是命名空间转向。 

## 为动态创建的对象设置智能提示

示例：

```aardio
/*intellisense()
!tray.delete() = 删除托盘图标
!tray.tip = 设置鼠标提示信息
!tray.pop("__","") = 弹出汽泡提示\n参数(提示信息,标题)
!tray.pop("__","",2) = 弹出汽泡提示\n参数(提示信息,标题,警告图标)
!tray.pop("__","",3) = 弹出汽泡提示\n参数(提示信息,标题,错误图标)
!tray.message = 指定回调消息\n当用户点击托盘图标时、向主窗体发送此消息
win.util.tray() = !tray. 
end intellisense*/
```  

对于动态创建的对象，必须使用感叹号作为首字符避免名字冲突。

在智能提示配置中使用下面的代码以声明调用 `win.util.tray()` 返回的对象由 `!tray` 提供智能提示。
 
`win.util.tray() = !tray.`

上面智能提示尾部必须是 `.`，后面不要有其他字符。

注意上面的括号中不能写参数，上面的格式声明对于 `win.util.tray()` 返回的对象(无论用户有没有写调用参数，也就是智能提示配置里不能写参数，但实际能有没有调用参数的写法都会生效)，将它们的代码提示全部重定向到`!tray`对象。


如果等号后面第一个字符是 `!`，那么输入 `win.util.tray()` 时不会显示提示。如果写为：

`win.util.tray() = @这是模板代码\n!tray.`

那么输入 `win.util.tray()` 时会显示提示。
  
上面的写法，可以在`!`前面,等号后面添加说明,但必须以`\n`换行符结束。格式如下:  

`win.util.tray() = 这是说明文字\n!tray.  `
  
注意命名空间重定向必须放在说明文字的尾部并且必须以 `\n!`开始，并以圆点`.`结束，后面不能有空格,  

也可以用这种方法来定义在 for 语句中迭代器函数返回的变量的智能提示。

再看一个示例：

```aardio
web.layout() = !wblayout.
!wblayout.getValueObject() = !layout_value.object.
```  

这种写法的好处是可以对一个函数返回值动态创建的对象，例如`!wblayout ` 再次定义它的成员函数返回的对象。 

注意无论是智能提示配置,或编辑普通源码时,等号右侧使用括号可能被识别为函数调用.  所以**在智能提示配置段中，应尽可能避免在说明文字中使用圆括号**。可以用中文圆括号替代。

## 函数调用连缀式 代码提示

```aardio
/*intellisense()
io.file() = !ioFile.
io.file().read(-1) = 读入全部内容 

!ioFile.xxx() = 代码提示\n!ioFile.
end intellisense*/
```  

上面的写法可以支持识别该函数的返回值,以及直接在函数调用语句后列出成员的连缀式写法。无论实际调用中使用了多少个参数,在这里不允许写参数，括号间不允许写空格。
  
## 在代码中定义智能提示

```aardio
/*intellisense(命名空间.命名空间)*/
testa = 提示文字
testb = 提示文字 

testa.b.c = 可使用圆点表示命名空间 
/*end intellisense*/
```  
 
这种方法是比较局限的，只能在中间写 aardio 代码，不能自由使用智能提示的配置语法，一般不建议使用。

## 使用智能提示

1. 您可用以下方式启动代码完成功能

自动：IDE会智能感知您输入的代码，并自动完成相关代码。  
手动：你可以按 `CTRL+J` 组合键调用智能提示并打开代码提示窗口。 也可以按 `CTRL + K` 刷新并修复智能提示数据。
  

2. 智能提示引擎按以下规律分析代码

*   当打开一个 aardio 代码文件时，解析全部代码的智能提示数据。
*   你输入完成一行代码、按回车键结束一行时，会分析这一行的智能提示数据。
*   当从窗体可视化设计模式切换到代码编辑模式，IDE 自动为窗体、控件创建智能提示数据，否则您无法获取完整的智能提示效果。
*   按 `CTRL+K` 组合热键时，更新当前文档相关的智能提示数据。

3. 窗口程序的智能提示

窗口程序必须在窗口设计器中打开，然后再切换到代码模式才能正常显示控件与窗口的提示。

aardio 发现代码有下面的窗口设计器标记就可用窗口设计器打开代码。

```aardio
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=469)
winform.add()
/*}}*/
```

如果移除 `/*DSG{{*/` 、`/*}}*/` 则 aardio 只会将其作为普通代码打开，也不会提供窗口控件的智能提示。