@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
[submodule "themes/hermit"] |
||||
path = themes/hermit |
||||
url = https://github.com/Track3/hermit.git |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
--- |
||||
title: "{{ replace .Name "-" " " | title }}" |
||||
date: {{ .Date }} |
||||
draft: true |
||||
--- |
||||
|
||||
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
baseURL = "https://oaoa.me" |
||||
languageCode = "en-us" |
||||
defaultContentLanguage = "en" |
||||
title = "个人博客" |
||||
theme = "hermit" |
||||
# enableGitInfo = true |
||||
pygmentsCodefences = true |
||||
pygmentsUseClasses = true |
||||
hasCJKLanguage = true # If Chinese/Japanese/Korean is your main content language, enable this to make wordCount works right. |
||||
rssLimit = 10 # Maximum number of items in the RSS feed. |
||||
copyright = "This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License." # This message is only used by the RSS template. |
||||
enableEmoji = true # Shorthand emojis in content files - https://gohugo.io/functions/emojify/ |
||||
# googleAnalytics = "UA-123-45" |
||||
# disqusShortname = "yourdiscussshortname" |
||||
|
||||
[author] |
||||
name = "lniwn" |
||||
|
||||
[blackfriday] |
||||
# hrefTargetBlank = true |
||||
# noreferrerLinks = true |
||||
# nofollowLinks = true |
||||
|
||||
[taxonomies] |
||||
tag = "tags" |
||||
category = "categories" |
||||
# Categories are disabled by default. |
||||
|
||||
[params] |
||||
dateform = "Jan 2, 2006" |
||||
dateformShort = "Jan 2" |
||||
dateformNum = "2006-01-02" |
||||
dateformNumTime = "2006-01-02 15:04 -0700" |
||||
|
||||
# Metadata mostly used in document's head |
||||
# description = "" |
||||
# images = [""] |
||||
themeColor = "#494f5c" |
||||
|
||||
homeSubtitle = "记录读书笔记和心得体会" |
||||
footerCopyright = ' · <a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener">CC BY-NC 4.0</a>' |
||||
# bgImg = "" # Homepage background-image URL |
||||
|
||||
# Prefix of link to the git commit detail page. GitInfo must be enabled. |
||||
# gitUrl = "https://github.com/username/repository/commit/" |
||||
|
||||
# Toggling this option needs to rebuild SCSS, requires Hugo extended version |
||||
justifyContent = false # Set "text-align: justify" to `.content`. |
||||
|
||||
relatedPosts = false # Add a related content section to all single posts page |
||||
|
||||
# Add custom css |
||||
# customCSS = ["css/foo.css", "css/bar.css"] |
||||
|
||||
# Social Icons |
||||
# Check https://github.com/Track3/hermit#social-icons for more info. |
||||
[[params.social]] |
||||
name = "twitter" |
||||
url = "https://twitter.com/sglshdo" |
||||
|
||||
[[params.social]] |
||||
name = "telegram" |
||||
url = "https://t.me/lniwn" |
||||
|
||||
[[params.social]] |
||||
name = "github" |
||||
url = "https://github.com/lniwn" |
||||
|
||||
[menu] |
||||
|
||||
[[menu.main]] |
||||
name = "Posts" |
||||
url = "posts/" |
||||
weight = 1 |
||||
|
||||
[[menu.main]] |
||||
name = "Categories" |
||||
url = "categories/" |
||||
weight = 2 |
||||
|
||||
[[menu.main]] |
||||
name = "Tags" |
||||
url = "tags/" |
||||
weight = 3 |
||||
|
||||
[[menu.main]] |
||||
name = "About" |
||||
url = "about/" |
||||
weight = 4 |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
+++ |
||||
title = "About Hugo" |
||||
date = "2014-04-09" |
||||
+++ |
||||
|
||||
Hugo is the **world’s fastest framework for building websites**. It is written in Go. |
||||
|
||||
It makes use of a variety of open source projects including: |
||||
|
||||
* https://github.com/russross/blackfriday |
||||
* https://github.com/alecthomas/chroma |
||||
* https://github.com/muesli/smartcrop |
||||
* https://github.com/spf13/cobra |
||||
* https://github.com/spf13/viper |
||||
|
||||
Learn more and contribute on [GitHub](https://github.com/gohugoio). |
||||
|
||||
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
--- |
||||
title: CMake学习笔记 |
||||
date: 2017-12-27 13:54:05 |
||||
tags: [cmake, visual studio] |
||||
categories: cmake |
||||
--- |
||||
|
||||
本文主要记录CMake学习过程的一些笔记。 |
||||
|
||||
<!-- more --> |
||||
|
||||
## 基本文件结构 |
||||
编写CMakeLists.txt |
||||
|
||||
``` |
||||
# CMake 最低版本号要求 |
||||
cmake_minimum_required (VERSION 2.8) |
||||
# 项目信息 |
||||
project (Demo1) |
||||
# 指定生成目标 |
||||
add_executable(Demo main.cc) |
||||
``` |
||||
|
||||
## 常用命令 |
||||
|
||||
### 项目类型命令 |
||||
- `add_executable`可执行文件 |
||||
- `add_library` 静态库 |
||||
|
||||
### 文件依赖命令 |
||||
- `aux_source_directory(<dir> <variable>)` |
||||
查找指定目录下的所有源文件,然后将结果保存进指定的变量名。 |
||||
``` |
||||
# CMake 最低版本号要求 |
||||
cmake_minimum_required (VERSION 2.8) |
||||
# 项目信息 |
||||
project (Demo2) |
||||
# 查找当前目录下的所有源文件 |
||||
# 并将名称保存到 DIR_SRCS 变量 |
||||
aux_source_directory(. DIR_SRCS) |
||||
# 指定生成目标 |
||||
add_executable(Demo ${DIR_SRCS}) |
||||
``` |
||||
这样,CMake 会将当前目录所有源文件的文件名赋值给变量`DIR_SRCS`,再指示变量`DIR_SRCS` 中的源文件需要编译成一个名称为 Demo 的可执行文件。 |
||||
|
||||
- `add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])` |
||||
添加子文件夹到构建系统中。 |
||||
`source_dir`子文件夹路径 |
||||
`binary_dir` 输出路径 |
||||
`EXCLUDE_FROM_ALL` 从Build All项目中排除 |
||||
|
||||
### 编译选项命令 |
||||
- Visual Studio to CMake Mapping |
||||
{% asset_img VS-to-CMake-Mapping.png VS-to-CMake-Mapping %} |
||||
{% asset_img CMake-Projects.png CMake-Projects %} |
||||
> ZERO_CHECK will rerun cmake. You can/should execute this after changing something on your CMake files. |
||||
> ALL_BUILD is simply a target which builds all and everything project in the active solution, I guess one can compare it to "make all". |
||||
> 可以通过`set(CMAKE_SUPPRESS_REGENERATION true)`不生成`ZERO_CHECK`工程。 |
||||
|
||||
### 链接命令 |
||||
- `target_link_libraries`指明链接库 |
||||
`target_link_libraries(<target> [lib1 [lib2 [...]]] [[debug|optimized|general] <lib>] ...)` |
||||
`general`可选字段,表示所有模式都链接的库 |
||||
`debug`表示debug模式才链接的库 |
||||
`optimized`表示非debug模式才链接的库 |
||||
|
||||
```cmake |
||||
target_link_libraries(${PROJECT_NAME} |
||||
delayimp.lib libcef.lib |
||||
debug cef_module_d.lib |
||||
debug libcef_dll_wrapper_d.lib |
||||
optimized cef_module.lib |
||||
optimized libcef_dll_wrapper.lib) |
||||
``` |
||||
|
||||
## 项目实例 |
||||
|
||||
### 自定义编译选项 |
||||
|
||||
顶层CMakeLists.txt文件 |
||||
``` |
||||
# CMake 最低版本号要求 |
||||
cmake_minimum_required (VERSION 2.8) |
||||
# 项目信息 |
||||
project (Demo4) |
||||
# 加入一个配置头文件,用于处理 CMake 对源码的设置 |
||||
configure_file ( |
||||
"${PROJECT_SOURCE_DIR}/config.h.in" |
||||
"${PROJECT_BINARY_DIR}/config.h" |
||||
) |
||||
# 是否使用自己的 MathFunctions 库 |
||||
option (USE_MYMATH |
||||
"Use provided math implementation" ON) |
||||
# 是否加入 MathFunctions 库 |
||||
if (USE_MYMATH) |
||||
include_directories ("${PROJECT_SOURCE_DIR}/math") |
||||
add_subdirectory (math) |
||||
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) |
||||
endif (USE_MYMATH) |
||||
# 查找当前目录下的所有源文件 |
||||
# 并将名称保存到 DIR_SRCS 变量 |
||||
aux_source_directory(. DIR_SRCS) |
||||
# 指定生成目标 |
||||
add_executable(Demo ${DIR_SRCS}) |
||||
target_link_libraries (Demo ${EXTRA_LIBS}) |
||||
``` |
||||
编写`config.h.in`文件 `#cmakedefine USE_MYMATH` |
||||
|
||||
### 设置编译模式 |
||||
|
||||
``` |
||||
set(CMAKE_BUILD_TYPE "Debug") |
||||
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") |
||||
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") |
||||
``` |
||||
|
||||
### 环境检查 |
||||
|
||||
首先在顶层 CMakeLists 文件中添加 CheckFunctionExists.cmake 宏,并调用 `check_function_exists` 命令测试链接器是否能够在链接阶段找到 pow 函数。 |
||||
``` |
||||
# 检查系统是否支持 pow 函数 |
||||
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) |
||||
check_function_exists (pow HAVE_POW) |
||||
``` |
||||
|
||||
### 设置libcurl运行时环境 |
||||
|
||||
```cmake |
||||
if(USE_ALLMT_) |
||||
target_compile_definitions(libcurl PRIVATE -DRTLIBCFG=static) |
||||
set_property(TARGET libcurl APPEND_STRING PROPERTY COMPILE_OPTIONS $<IF:$<CONFIG:Debug>,/MTd,/MT>) |
||||
else() |
||||
target_compile_definitions(libcurl PRIVATE -DRTLIBCFG=shared) |
||||
set_property(TARGET libcurl APPEND_STRING PROPERTY COMPILE_OPTIONS $<IF:$<CONFIG:Debug>,/MDd,/MD>) |
||||
endif() |
||||
``` |
||||
|
||||
## 参考链接 |
||||
- [<i class="icon-gittip"></i>cmake-and-visual-studio](https://cognitivewaves.wordpress.com/cmake-and-visual-studio/) |
||||
- [<i class="icon-gittip"></i>CMake手册](https://www.zybuluo.com/khan-lau/note/254724) |
||||
- [<i class="icon-gittip"></i>CMakeLists.txt](http://wiki.ros.org/catkin/CMakeLists.txt) |
||||
|
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
--- |
||||
title: CMake项目添加预编译头 |
||||
date: 2017-12-28 11:46:13 +08:00 |
||||
tags: [cmake, visual studio] |
||||
images: ["apple-touch-icon.png"] |
||||
categories: cmake |
||||
--- |
||||
|
||||
本文主要记录为CMake项目添加预编译头支持,以及过程中遇到的坑,比如`set_target_properties`连续调用两次失效的问题。 |
||||
|
||||
<!-- more --> |
||||
|
||||
各个编译器支持预编译头指令不同,这里仅以Visual Studio为例进行说明。 |
||||
|
||||
## 操作步骤 |
||||
|
||||
- 创建cmake宏文件`PrecompiledHeader.cmake` |
||||
|
||||
```cmake PrecompiledHeader.cmake |
||||
#------------------------------------------------------- |
||||
# Support macro to use a precompiled header |
||||
# Usage: |
||||
# use_precompiled_header(TARGET HEADER_FILE SRC_FILE) |
||||
#------------------------------------------------------- |
||||
|
||||
macro(use_precompiled_header TARGET HEADER_FILE SRC_FILE) |
||||
get_filename_component(HEADER ${HEADER_FILE} NAME) |
||||
|
||||
# Use MSVC_IDE to exclude NMake from using PCHs |
||||
if (MSVC AND NOT NMAKE AND NOT OGRE_UNITY_BUILD) |
||||
|
||||
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY |
||||
COMPILE_FLAGS " /Yu\"${HEADER}\"") |
||||
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY |
||||
COMPILE_FLAGS " /FI\"${HEADER}\"") |
||||
set_source_files_properties(${SRC_FILE} |
||||
PPROPERTIES COMPILE_FLAGS /Yc"${HEADER}") |
||||
elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX) |
||||
endif () |
||||
endmacro(use_precompiled_header) |
||||
``` |
||||
|
||||
- 在主工程的`CMakeLists.txt`中添加依赖 |
||||
|
||||
```cmake |
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/Tools/CMake) |
||||
include(PrecompiledHeader) |
||||
``` |
||||
|
||||
- 在需要使用预编译头的项目中调用`use_precompiled_header`宏函数 |
||||
|
||||
```cmake |
||||
use_precompiled_header(${PROJECT_NAME} |
||||
"${CMAKE_CURRENT_SOURCE_DIR}/stdafx.h" |
||||
"${CMAKE_CURRENT_SOURCE_DIR}/stdafx.cpp") |
||||
``` |
||||
|
||||
## 踩坑记录 |
||||
|
||||
- set_target_properties连续调用两次,导致前一次调用无效 |
||||
|
||||
在`PrecompiledHeader.cmake`文件中,最开始使用了如下的代码 |
||||
|
||||
{% note danger %} |
||||
|
||||
{% codeblock lang:cmake %} |
||||
if (MSVC AND NOT NMAKE AND NOT OGRE_UNITY_BUILD) |
||||
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS /Yu"${HEADER}") |
||||
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS /FI"${HEADER}") |
||||
set_source_files_properties(${SRC_FILE} |
||||
PPROPERTIES COMPILE_FLAGS /Yc"${HEADER}" |
||||
) |
||||
{% endcodeblock %} |
||||
|
||||
{% endnote %} |
||||
|
||||
可是发现永远只有/FI生效,后来查找了大量资料,替换为了`set_property APPEND`的形式,才最终解决。 |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
--- |
||||
title: Cef Bug Fix List |
||||
date: 2017-12-20 16:59:50 |
||||
tags: [cef, cplusplus] |
||||
categories: cplusplus |
||||
--- |
||||
|
||||
本文主要记录在cef开发过程中发现的bug及解决方法。 |
||||
|
||||
<!-- more --> |
||||
|
||||
## 解决CEF中html页面不显示鼠标tips的bug |
||||
|
||||
在预编译头文件`stdafx.h`最下方加入: |
||||
|
||||
```c |
||||
#ifdef _UNICODE |
||||
#if defined _M_IX86 |
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#elif defined _M_IA64 |
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#elif defined _M_X64 |
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#else |
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#endif |
||||
#endif |
||||
``` |
||||
|
||||
> VS2015自动生成的manifest如下,去掉了ia64选项: |
||||
|
||||
```c |
||||
#ifdef _UNICODE |
||||
#if defined _M_IX86 |
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#elif defined _M_X64 |
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#else |
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") |
||||
#endif |
||||
#endif |
||||
``` |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
--- |
||||
title: Python模块timezone学习笔记 |
||||
date: 2018-08-06 18:19:30 |
||||
tags: [python] |
||||
categories: python |
||||
--- |
||||
本文基于python3,记录了datetime包中的timezone用法。 |
||||
<!-- more --> |
||||
|
||||
使用第三方扩展包pytz,构造指定时区。 |
||||
|
||||
> **astimezone** |
||||
|
||||
`datetime.datetime.astimezone`是将原始输入解释为本地时区,然后再转换为目标时区,而pytz包的`localize`方法,是将原始输入直接解释为目标时区,例如: |
||||
|
||||
```python |
||||
tz = pytz.timezone('Asia/Shanghai') |
||||
target_dt = datetime.datetime(2018, 8, 5, 0, 0, 0, 0) |
||||
print(repr(target_dt.astimezone(tz))) |
||||
print(repr(tz.localize(target_dt))) |
||||
|
||||
# Output |
||||
# > datetime.datetime(2018, 8, 5, 8, 0, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>) |
||||
# > datetime.datetime(2018, 8, 5, 0, 0, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>) |
||||
``` |
||||
|
||||
> **timetuple** |
||||
|
||||
由于`datetime.datetime.timetuple`方法不存储时区,所以如果需要构造不同时区的timestamp,需要使用`datetime.datetime.utctimetuple`方法。 |
||||
|
||||
```python |
||||
target_dt = datetime.datetime(2018, 8, 5, 0, 0, 0, 0) |
||||
print(repr(target_dt.utctimetuple())) |
||||
print(repr(target_dt.timetuple())) |
||||
|
||||
# Output |
||||
# > time.struct_time(tm_year=2018, tm_mon=8, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=217, tm_isdst=0) |
||||
# > time.struct_time(tm_year=2018, tm_mon=8, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=217, tm_isdst=-1) |
||||
``` |
||||
|
||||
> `datetime.``timetuple`()[¶](https://docs.python.org/3/library/datetime.html#datetime.datetime.timetuple) |
||||
> |
||||
> Return a [`time.struct_time`](https://docs.python.org/3/library/time.html#time.struct_time) such as returned by [`time.localtime()`](https://docs.python.org/3/library/time.html#time.localtime). `d.timetuple()` is equivalent to `time.struct_time((d.year, d.month, d.day, d.hour, d.minute, d.second, d.weekday(), yday, dst))`, where `yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1` is the day number within the current year starting with `1` for January 1st. The `tm_isdst` flag of the result is set according to the [`dst()`](https://docs.python.org/3/library/datetime.html#datetime.datetime.dst) method: [`tzinfo`](https://docs.python.org/3/library/datetime.html#datetime.datetime.tzinfo) is `None` or [`dst()`](https://docs.python.org/3/library/datetime.html#datetime.datetime.dst) returns `None`, `tm_isdst` is set to `-1`; else if [`dst()`](https://docs.python.org/3/library/datetime.html#datetime.datetime.dst) returns a non-zero value, `tm_isdst`is set to `1`; else `tm_isdst` is set to `0`. |
||||
|
||||
> `datetime.``utctimetuple`()[¶](https://docs.python.org/3/library/datetime.html#datetime.datetime.utctimetuple) |
||||
> |
||||
> If [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instance *d* is naive, this is the same as `d.timetuple()` except that `tm_isdst` is forced to 0 regardless of what `d.dst()` returns. DST is never in effect for a UTC time. |
||||
> |
||||
> If *d* is aware, *d* is normalized to UTC time, by subtracting `d.utcoffset()`, and a [`time.struct_time`](https://docs.python.org/3/library/time.html#time.struct_time) for the normalized time is returned. `tm_isdst` is forced to 0. Note that an [`OverflowError`](https://docs.python.org/3/library/exceptions.html#OverflowError) may be raised if *d*.year was`MINYEAR` or `MAXYEAR` and UTC adjustment spills over a year boundary. |
||||
|
||||
目标需求,将东8区(+8)的`2018-08-05 00:00:00`转换为unix timestamp: |
||||
|
||||
```python |
||||
tz = pytz.timezone('Asia/Shanghai') |
||||
target_dt = datetime.datetime(2018, 8, 5, 0, 0, 0, 0) |
||||
target_dt = tz.localize(target_dt) |
||||
print(time.mktime(target_dt.utctimetuple())) |
||||
print(target_dt.timestamp()) |
||||
|
||||
# Output |
||||
# > 1533398400.0 |
||||
# > 1533398400.0 |
||||
``` |
||||
|
||||
参考文档: |
||||
|
||||
https://kkc.github.io/2015/07/08/dealing-with-datetime-and-timezone-in-python/ |
||||
@ -0,0 +1,135 @@
@@ -0,0 +1,135 @@
|
||||
--- |
||||
title: Vim快捷键备忘录 |
||||
date: 2018-10-17 10:17:49 |
||||
tags: [vim] |
||||
categories: daily |
||||
--- |
||||
Vim快捷键查询。 |
||||
<!-- more --> |
||||
|
||||
## 光标移动 |
||||
|
||||
| 命令 | 作用 | |
||||
| ----------------- | ------------------------------------------ | |
||||
| h,j,k,l | h表示往左,j表示往下,k表示往上,l表示往右 | |
||||
| ctrl+f | 上一页 | |
||||
| ctrl+b | 下一页 | |
||||
| w,e,W,E | 跳到单词的后面,小写包括标点 | |
||||
| b,B | 跳到单词的前面,小写包括标点 | |
||||
| 0 | 跳到本行的头部 | |
||||
| ^ | 跳到一行的开始 | |
||||
| $ | 跳到一行的结尾 | |
||||
| gg | 文档的第一行 | |
||||
| [N]G | 文档的第N行(G是最后一行),如:27G | |
||||
| f`space`,F`space` | 移动到右边的空格,大写移动到左边的空格 | |
||||
|
||||
|
||||
|
||||
## 插入 |
||||
|
||||
| 命令 | 作用 | |
||||
| ---- | -------------------------- | |
||||
| i | 插入到光标前面 | |
||||
| I | 插入到行的开始位置 | |
||||
| a | 插入到光标的后面 | |
||||
| A | 插入到行的最后位置 | |
||||
| o | 在当前光标的下方插入新一行 | |
||||
| O | 在当前光标的上方插入新一行 | |
||||
| Esc | 关闭插入模式 | |
||||
| | | |
||||
| | | |
||||
| | | |
||||
| | | |
||||
|
||||
|
||||
|
||||
## 编辑 |
||||
|
||||
| 命令 | 作用 | |
||||
| ------ | -------------------------------------- | |
||||
| r | 替换光标所在的一个字符 | |
||||
| J | 合并下一行到当前行 | |
||||
| s | 删除光标所在的一个字符,光标还在当前行 | |
||||
| S | 删除光标所在行的内容,光标还在当前行 | |
||||
| u | 撤销上一步操作 | |
||||
| U | 撤销当前行的更改 | |
||||
| ctrl+r | 恢复上一步操作 | |
||||
| . | 重复最后一个命令 | |
||||
| ~ | 变换为大写 | |
||||
| [N]>> | 一行或N行往右移动一个tab | |
||||
| [N]<< | 一行或N行往左移动一个tab | |
||||
| | | |
||||
|
||||
|
||||
|
||||
## 退出 |
||||
|
||||
| 命令 | 作用 | |
||||
| ------ | ---------------- | |
||||
| :w | 保存 | |
||||
| :wq,:x | 保存并关闭 | |
||||
| :q | 关闭(已保存) | |
||||
| :q! | 强制关闭,不保存 | |
||||
| | | |
||||
|
||||
|
||||
|
||||
## 查找和搜索 |
||||
|
||||
| 命令 | 作用 | |
||||
| -------------------- | ------------------------------------------------------------ | |
||||
| /pattern | 搜索(非插入模式),支持正则 | |
||||
| ?pattern | 往后搜索 | |
||||
| n | 当前搜索结果的下一个目标 | |
||||
| N | 当前搜索结果的上一个目标 | |
||||
| rp | 将光标之后的字符替换为字母p | |
||||
| :s/word/replace | 光标所在行的第一个word替换为replace | |
||||
| :%s/word/replace | 全文查找word并替换为replace | |
||||
| :1,50s/word/replace | 在第1行和第50行之间(含)进行搜索和替换 | |
||||
| :45s/word/replace/ | 表示仅仅在第45行进行搜索和替换。而 1,$ 行号范围和 % 是等价的 | |
||||
| :%s/^/要插入的字符串 | 每行开头插入字符串 | |
||||
| :%s/$/要插入的字符串 | 每行结尾插入字符串 | |
||||
|
||||
|
||||
|
||||
## 剪切、复制和粘贴 |
||||
|
||||
| 命令 | 作用 | |
||||
| ----- | ------------------------------------------------------------ | |
||||
| dd | 删除一行,同时被删除内容存于剪贴板上 | |
||||
| de | 删除光标后的单词内容,同时被删除内容存于剪贴板上 | |
||||
| dG | 删除当前位置到文件结尾内容 | |
||||
| dw | 删除光标后的单词内容以及之后的空格,同时被删除内容存于剪贴板上 | |
||||
| [N]dd | 删除以当前行开始的n行 | |
||||
| x | 删除后一个字符 | |
||||
| X | 删除前一个字符 | |
||||
| D | 删除当前位置到行末的内容 | |
||||
| [N]yy | 复制一行或者N行 | |
||||
| yw | 复制一个单词 | |
||||
| p | 粘贴 | |
||||
|
||||
|
||||
|
||||
## 窗口操作 |
||||
|
||||
| 命令 | 作用 | |
||||
| ------- | ------------------------------------------------------------ | |
||||
| :split | 水平方向分割出一个窗口 | |
||||
| :vsplit | 垂直方向分割出一个窗口 | |
||||
| :close | 关闭窗口 | |
||||
| ctrl+w | 切换窗口, h到左边窗口,j到下方窗口,k到上方窗口,l到右边窗口 | |
||||
|
||||
## 常用操作 |
||||
|
||||
| 命令 | 作用 | |
||||
| ------- | --------------------------------- | |
||||
| gg + dG | 清空文件内容 | |
||||
| viw,vaw | 选中光标所在单词(vaw包括前后空格) | |
||||
| | | |
||||
|
||||
|
||||
|
||||
## 在线文档 |
||||
- [VIM QUICK REFERENCE CARD](http://tnerual.eriogerg.free.fr/vimqrc.pdf) |
||||
- {% asset_img morden1.png 增强版 %} |
||||
- {% asset_img text1.png 文字版 %} |
||||
@ -0,0 +1,169 @@
@@ -0,0 +1,169 @@
|
||||
--- |
||||
title: office2016激活步骤 |
||||
date: 2018-09-28 20:32:30 |
||||
tags: [教程] |
||||
categories: windows |
||||
--- |
||||
|
||||
office2016激活方法。 |
||||
<!-- more --> |
||||
|
||||
## 1. Retail版本转VOL版本 |
||||
```bat |
||||
cd /d "C:\Program Files (x86)\Microsoft Office\Office16" |
||||
cscript ospp.vbs /dstatus |
||||
``` |
||||
Retail版显示`LICENSE DESCRIPTION: Office 15, RETAIL(Grace) channel`,VOL版显示`LICENSE DESCRIPTION: Office 15, VOLUME_KMSCLIENT channel` |
||||
|
||||
- 32位版本Office转换代码 |
||||
```bat |
||||
@echo off |
||||
:ADMIN |
||||
openfiles >nul 2>nul ||( |
||||
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" |
||||
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" |
||||
"%temp%\getadmin.vbs" >nul 2>&1 |
||||
goto:eof |
||||
) |
||||
del /f /q "%temp%\getadmin.vbs" >nul 2>nul |
||||
|
||||
for /f "tokens=6 delims=[]. " %%G in ('ver') do set win=%%G |
||||
|
||||
pushd "%~dp0" |
||||
Title Office 2016 Retail to Volume License Converter |
||||
|
||||
echo Press Enter to start VL-Conversion... |
||||
echo. |
||||
pause |
||||
echo. |
||||
cd /D "%SystemRoot%\System32" |
||||
|
||||
if %win% GEQ 9200 ( |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul-oob.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-bridge-office.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-root.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-root-bridge-test.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-stil.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-ul.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-ul-oob.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\pkeyconfig-office.xrm-ms |
||||
) |
||||
if %win% LSS 9200 ( |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul-oob.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-bridge-office.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-root.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-root-bridge-test.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-stil.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-ul.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\client-issuance-ul-oob.xrm-ms |
||||
cscript "%ProgramFiles(x86)%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles(x86)%\Microsoft Office\root\Licenses16\pkeyconfig-office.xrm-ms |
||||
) |
||||
echo. |
||||
echo Retail to Volume License conversion finished. |
||||
echo. |
||||
pause |
||||
``` |
||||
- 64位版本office转换代码 |
||||
```bat |
||||
@echo off |
||||
:ADMIN |
||||
openfiles >nul 2>nul ||( |
||||
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" |
||||
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" |
||||
"%temp%\getadmin.vbs" >nul 2>&1 |
||||
goto:eof |
||||
) |
||||
del /f /q "%temp%\getadmin.vbs" >nul 2>nul |
||||
|
||||
for /f "tokens=6 delims=[]. " %%G in ('ver') do set win=%%G |
||||
|
||||
pushd "%~dp0" |
||||
Title Office 2016 Retail to Volume License Converter |
||||
|
||||
echo Press Enter to start VL-Conversion... |
||||
echo. |
||||
pause |
||||
echo. |
||||
cd /D "%SystemRoot%\System32" |
||||
|
||||
if %win% GEQ 9200 ( |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul-oob.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-bridge-office.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-root.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-root-bridge-test.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-stil.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-ul.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-ul-oob.xrm-ms |
||||
cscript slmgr.vbs /ilc "%ProgramFiles%\Microsoft Office\root\Licenses16\pkeyconfig-office.xrm-ms |
||||
) |
||||
if %win% LSS 9200 ( |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProPlusVL_KMS_Client-ul-oob.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\ProjectProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ppd.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul-oob.xrm-ms" |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\VisioProVL_KMS_Client-ul.xrm-ms" |
||||
|
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-bridge-office.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-root.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-root-bridge-test.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-stil.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-ul.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\client-issuance-ul-oob.xrm-ms |
||||
cscript "%ProgramFiles%\Microsoft Office\Office16\ospp.vbs" /inslic:"%ProgramFiles%\Microsoft Office\root\Licenses16\pkeyconfig-office.xrm-ms |
||||
) |
||||
echo. |
||||
echo Retail to Volume License conversion finished. |
||||
echo. |
||||
pause |
||||
``` |
||||
|
||||
## 2. 一键激活 |
||||
```bat |
||||
cd /d "C:\Program Files (x86)\Microsoft Office\Office16" |
||||
cscript ospp.vbs /inpkey:XQNVK-8JYDB-WJ9W3-YJ8YR-WFG99 |
||||
cscript ospp.vbs /sethst:kms.library.hk |
||||
cscript ospp.vbs /act |
||||
``` |
||||
|
||||
> 参考页面: |
||||
> - https://kms.library.hk/archives/kms.html |
||||
> - https://0w0.pw/216.html |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
--- |
||||
title: 一句话Windows |
||||
date: 2017-12-20 20:54:38 |
||||
tags: [windows, cplusplus] |
||||
categories: windows |
||||
--- |
||||
|
||||
本文主要记录windows开发中遇到的一句话技巧和知识点。 |
||||
|
||||
<!-- more --> |
||||
|
||||
--- |
||||
## 为VC++ 2008添加application compatibility段 |
||||
|
||||
使用visual studio为应用程序添加manifest方法很简单,下面为常用的一个manifest文件 |
||||
|
||||
```xml |
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||
<assembly manifestversion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
||||
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3"> |
||||
<security> |
||||
<requestedprivileges> |
||||
<requestedexecutionlevel level="asInvoker" uiaccess="false"> |
||||
</requestedexecutionlevel> |
||||
</requestedprivileges> |
||||
</security> |
||||
</trustinfo> |
||||
<dependency> |
||||
<dependentassembly> |
||||
<assemblyidentity name="Microsoft.VC90.CRT" processorarchitecture="x86" publickeytoken="1fc8b3b9a1e18e3b" type="win32" version="9.0.21022.8"> |
||||
</assemblyidentity> |
||||
</dependentassembly> |
||||
</dependency> |
||||
<dependency> |
||||
<dependentassembly> |
||||
<assemblyidentity language="*" name="Microsoft.Windows.Common-Controls" processorarchitecture="x86" publickeytoken="6595b64144ccf1df" type="win32" version="6.0.0.0"> |
||||
</assemblyidentity> |
||||
</dependentassembly> |
||||
</dependency> |
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
||||
<application> |
||||
<!-- Windows 10 --> |
||||
<supportedos id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"> |
||||
</supportedos> |
||||
<!-- Windows 8.1 --> |
||||
<supportedos id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"> |
||||
</supportedos> |
||||
<!-- Windows Vista --> |
||||
<supportedos id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"> |
||||
</supportedos> |
||||
<!-- Windows 7 --> |
||||
<supportedos id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"> |
||||
</supportedos> |
||||
<!-- Windows 8 --> |
||||
<supportedos id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"> |
||||
</supportedos> |
||||
</application> |
||||
</compatibility> |
||||
</assembly> |
||||
``` |
||||
|
||||
但是由于visual Studio2008不支持compatibility字段,直接这样添加会报错,所以需要先正常生成文件,然后再使用新版的mt.exe手动嵌入manifest文件。 |
||||
|
||||
使用mt.exe为程序添加manifest文件的命令很简单: |
||||
``mt.exe -nologo -manifest "r:\shared\hl.exe.manifest" -outputresource:"r:\shared\hl33m.exe;#1"`` |
||||
|
||||
[参考页面](https://blogs.msdn.microsoft.com/yvesdolc/2009/09/26/how-to-add-the-application-compatibility-section-with-visual-c-2008/) |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
--- |
||||
title: 为Hexo博客Next主题添加Schnack评论 |
||||
date: 2017-12-21 17:11:31 |
||||
tags: [vps, hexo] |
||||
categories: vps |
||||
--- |
||||
本文主要记录schnack评论搭建步骤(服务端搭建未完成)。 |
||||
<!-- more --> |
||||
|
||||
> **Step 1** |
||||
|
||||
在`%BLOG_PATH%\themes\next\layout\_third-party\comments`路径下创建`schnack.swig`文件 |
||||
|
||||
```swig |
||||
{% if theme.schnack and theme.schnack.enable %} |
||||
<script src="//blog.oaoa.me/embed.js" |
||||
data-schnack-slug="post-slug" |
||||
data-schnack-target=".comments"> |
||||
</script> |
||||
{% endif %} |
||||
``` |
||||
|
||||
> **Step 2** |
||||
|
||||
在`%BLOG_PATH%\themes\next\layout\_third-party\comments\index.swig`文件中添加`schnack.swig`的引用 |
||||
|
||||
```swig |
||||
{% include 'schnack.swig' %} |
||||
``` |
||||
|
||||
> **Step 3** |
||||
|
||||
在`%BLOG_PATH%\themes\next\layout\_partials\comments.swig`文件中,添加一个elseif代码块: |
||||
|
||||
```swig |
||||
{% elseif theme.schnack and schnack.enable %} |
||||
<div class="comments" id="comments"> |
||||
</div> |
||||
``` |
||||
|
||||
> **Step 4** |
||||
|
||||
**TODO: 服务端配置** |
||||
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
--- |
||||
title: 为Hexo博客Next主题添加Wildfire评论系统 |
||||
date: 2017-12-26 14:18:11 |
||||
tags: [vps, hexo] |
||||
categories: vps |
||||
--- |
||||
|
||||
本文主要记录[Wildfire](https://github.com/cheng-kang/wildfire)评论系统搭建的过程。 |
||||
|
||||
<!-- more --> |
||||
|
||||
## Hexo配置步骤 |
||||
|
||||
{% note primary %} Step 1 {% endnote %} |
||||
|
||||
关于wildfire的设置,请直接参考{% link 官方帮助文档 https://wildfire.js.org/#/zh-cn/usage?id=%e4%bd%bf%e7%94%a8%e8%af%b4%e6%98%8e %}。 |
||||
|
||||
{% note primary %} Step 2 {% endnote %} |
||||
|
||||
在`%BLOG_PATH%\themes\next\layout\_third-party\comments`路径下创建`wildfire.swig`文件 |
||||
|
||||
```swig |
||||
{% if page.comments and theme.wildfire.enable %} |
||||
<script type="text/javascript"> |
||||
var wildfireConfig = () => ({ |
||||
databaseProvider: '{{ theme.wildfire.database_provider }}', |
||||
databaseConfig: { |
||||
{% if (theme.wildfire.database_provider) === 'wilddog' %} |
||||
siteId: '{{ theme.wildfire.site_id }}' |
||||
{% elseif (theme.wildfire.database_provider) === 'firebase' %} |
||||
apiKey: '{{ theme.wildfire.api_key }}', |
||||
authDomain: '{{ theme.wildfire.auth_domain }}', |
||||
databaseURL: '{{ theme.wildfire.database_url }}', |
||||
projectId: '{{ theme.wildfire.project_id }}', |
||||
storageBucket: '{{theme.wildfire.storage_bucket}}', |
||||
messagingSenderId: '{{theme.wildfire.messaging_sender_id}}' |
||||
{% endif %} |
||||
}, |
||||
theme: '{{theme.wildfire.theme}}', |
||||
locale: '{{theme.wildfire.locale}}' |
||||
}) |
||||
</script> |
||||
<script type="text/javascript" src='//unpkg.com/wildfire/dist/wildfire.auto.js'></script> |
||||
{% endif %} |
||||
``` |
||||
|
||||
{% note primary %} Step 3 {% endnote %} |
||||
|
||||
在{% quote %}%BLOG_PATH%\themes\next\layout\_third-party\comments\index.swig{% endquote %}文件中添加wildfire.swig的引用: |
||||
{% code lang:swig %} |
||||
{% raw %}{% include 'wildfire.swig' %}{% endraw %} |
||||
{% endcode%} |
||||
|
||||
{% note primary %} Step 4 {% endnote %} |
||||
|
||||
在`%BLOG_PATH%\themes\next\layout\_partials\comments.swig`文件中,添加一个elseif代码块: |
||||
|
||||
```swig |
||||
{% elseif theme.wildfire.enable %} |
||||
<div class="comments" id="comments"> |
||||
<div class="wildfire_thread"></div> |
||||
</div> |
||||
``` |
||||
|
||||
## 遇到的坑 |
||||
- [x] 由于之前配置过valine的评论系统,后来添加了wildfire后死活不生效,重试了好多遍,最后无意中发现valine的bug,原代码如下: |
||||
|
||||
```swig |
||||
{% elseif theme.valine.appid and theme.valine.appkey %} |
||||
<div class="comments" id="comments"> |
||||
</div> |
||||
|
||||
{% elseif theme.wildfire.enable %} |
||||
<div class="comments" id="comments"> |
||||
<div class="wildfire_thread"></div> |
||||
</div> |
||||
``` |
||||
|
||||
修改后如下: |
||||
|
||||
```swig |
||||
{% elseif theme.valine.enable and theme.valine.appid and theme.valine.appkey %} |
||||
<div class="comments" id="comments"> |
||||
</div> |
||||
|
||||
{% elseif theme.wildfire.enable %} |
||||
<div class="comments" id="comments"> |
||||
<div class="wildfire_thread"></div> |
||||
</div> |
||||
``` |
||||
|
||||
因为我禁用valine的时候只是把_config.yml里面的enable改为了false,valine的appid和appkey都是有效值,所以导致这里的判断进入了valine分支。 |
||||
|
||||
- [x] ~~页面会有报错 `GET https://api.ipify.org/?format=json net::ERR_BLOCKED_BY_CLIENT`,暂时未解决,等待原作者处理。~~ |
||||
- [x] ~~页面url不能有中文,否则Edge浏览器会一直处于`正在启动 Wildfire……`中。~~ |
||||
- [x] ~~`pageURL`字段必须经过url编码,否则会报错,临时解决方案为:{% quote %} |
||||
{% raw %}pageURL: '{{page.permalink|url_encode}}'{% endraw %} |
||||
{% endquote%}~~ |
||||
|
||||
## 参考文章 |
||||
[在Hexo.NexT主题中部署Wildfire评论系统](http://mrliao.cn/2017/12/25/%E5%9C%A8Hexo.NexT%E4%B8%BB%E9%A2%98%E4%B8%AD%E9%83%A8%E7%BD%B2Wildfire%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F/) |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
--- |
||||
title: 加快Visual Studio编译速度 |
||||
date: 2018-01-05 12:08:32 |
||||
tags: [visual studio, cplusplus] |
||||
categories: windows |
||||
--- |
||||
|
||||
为Visual Studio开启多核编译支持,Visual Studio 2010及以上版本,直接可以在界面配置,而Visual Studio 2008则需要手动增加编译命令。 |
||||
|
||||
<!--more--> |
||||
|
||||
## Build with Multiple Processes |
||||
|
||||
Visual Studio并行编译选项命令为/MP,具体语法为: |
||||
|
||||
> `/MP[processMax]` |
||||
|
||||
`processMax` 为可选参数,范围为`1-65536`,表示可以创建的并行进程数,如果省略该参数,默认为[有效内核数](https://msdn.microsoft.com/en-us/library/bb385193.aspx#effective_processors),计算方法为:` (8 effective processors) = (2 physical processors) x (2 cores per physical processor) x (2 effective processors per core because of hyperthreading)`。 |
||||
|
||||
`/MP`选项会与下表中的选项冲突,所以如果需要开启`/MP`,需要关闭下表中其他选项,Visual Studio默认配置下debug模式会启用`/Gm`选项,需要手动关闭。 |
||||
|
||||
| Option or Language Feature | Description | |
||||
| ---------------------------------------- | ---------------------------------------- | |
||||
| [#import](https://msdn.microsoft.com/en-us/library/8etzzkb6.aspx) preprocessor directive | Converts the types in a type library into C++ classes, and then writes those classes to a header file. | |
||||
| [/E](https://msdn.microsoft.com/en-us/library/3xkfswhy.aspx), [/EP](https://msdn.microsoft.com/en-us/library/becb7sys.aspx) | Copies preprocessor output to the standard output (**stdout**). | |
||||
| [/Gm](https://msdn.microsoft.com/en-us/library/kfz8ad09.aspx) | Enables an incremental rebuild. | |
||||
| [/showIncludes](https://msdn.microsoft.com/en-us/library/hdkef6tk.aspx) | Writes a list of include files to the standard error (**stderr**). | |
||||
| [/Yc](https://msdn.microsoft.com/en-us/library/7zc28563.aspx) | Writes a precompiled header file. | |
||||
|
||||
|
||||
|
||||
## 为Visual Studio 2010开启多核并行编译 |
||||
|
||||
- 属性 -> 配置属性 -> C/C++ -> 常规 -> 多处理器编译,设为`是`。[^1] |
||||
- 属性 -> 配置属性 -> C/C++ -> 代码生成 -> 启用最小重新生成,设为`否`。[^2] |
||||
- 工具 -> 选项 -> 项目和解决方案 -> 生成并运行,设置`最大并行项目生成数`为8(*可以自定义合理值*)。 |
||||
|
||||
|
||||
|
||||
## 为Visual Studio 2008开启多核并行编译 |
||||
|
||||
- 属性 -> 配置属性 -> C/C++ -> 命令行 -> 附加选项,添加`/MP`。[^1] |
||||
- 属性 -> 配置属性 -> C/C++ -> 代码生成 -> 启用最小重新生成,设为`否`。[^2] |
||||
- 工具 -> 选项 -> 项目和解决方案 -> 生成并运行,设置`最大并行项目生成数`为8(*可以自定义合理值*)。 |
||||
|
||||
|
||||
|
||||
## 实例说明 |
||||
|
||||
以我自己的项目为例,不开启`/MP`选项,完整编译一次时间为48秒,开启之后完整编译一次时间为26秒。 |
||||
|
||||
{% asset_img before.png 不开启/MP选项 %} |
||||
|
||||
{% asset_img after.png 开启/MP选项 %} |
||||
|
||||
|
||||
[^1]: 启用`/MP`编译选项 |
||||
[^2]: 禁用`/Gm`编译选项 |
||||
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
--- |
||||
title: 动态获取当前模块的HMODULE/HINSTANCE值 |
||||
date: 2018-05-14 18:38:45 |
||||
tags: [win32] |
||||
categories: windows |
||||
--- |
||||
|
||||
如何动态获取当前代码运行时所在的模块句柄?这里介绍三种方法。 |
||||
|
||||
<!-- more --> |
||||
|
||||
## 1. 使用GetModuleHandle |
||||
|
||||
这是标准方案,可以动态获取exe或者dll模块句柄。 |
||||
|
||||
```c++ |
||||
HMODULE WINAPI GetModuleHandle( |
||||
_In_opt_ LPCTSTR lpModuleName |
||||
); |
||||
``` |
||||
|
||||
其中`lpModuleName`为dll或者exe名,如果扩展名被省略,默认会追加.dll后缀。如果结尾为`.`,则表示模块没有后缀名。一般来说,只需要执行模块名就可以了,如果指定了完整路径,分隔符必须使用`\`,不能使用`/`,如果使用`NULL`,则返回创建当前进程的exe句柄。另外,如果dll文件是以资源文件形式被加载,即指定了`LOAD_LIBRARY_AS_DATAFILE`,是无法使用该函数获取到句柄的。 |
||||
|
||||
## 2. 使用VirtualQuery |
||||
|
||||
函数原型为 |
||||
|
||||
```c++ |
||||
SIZE_T WINAPI VirtualQuery( |
||||
_In_opt_ LPCVOID lpAddress, |
||||
_Out_ PMEMORY_BASIC_INFORMATION lpBuffer, |
||||
_In_ SIZE_T dwLength |
||||
); |
||||
``` |
||||
|
||||
其中,`MEMORY_BASIC_INFORMATION `结构体中的`AllocationBase `就是模块基址,可以转换成模块句柄。 |
||||
|
||||
```c++ |
||||
typedef struct _MEMORY_BASIC_INFORMATION { |
||||
PVOID BaseAddress; |
||||
PVOID AllocationBase; |
||||
DWORD AllocationProtect; |
||||
SIZE_T RegionSize; |
||||
DWORD State; |
||||
DWORD Protect; |
||||
DWORD Type; |
||||
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; |
||||
``` |
||||
|
||||
## 3. 使用伪变量__ImageBase |
||||
|
||||
```c++ |
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase; |
||||
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) |
||||
``` |
||||
|
||||
如果使用Microsoft链接器,就可以使用上面的方法来获取当前代码所在模块的句柄。伪变量`__ImageBase `表示模块的DOS头,即这个模块的起始地址。 |
||||
|
||||
一般使用场景为,编写了一个静态库,提供给其他人调用,需要动态获取运行时所在模块的句柄。 |
||||
|
||||
```c++ |
||||
#if _MSC_VER >= 1300 // for VC 7.0 |
||||
// from ATL 7.0 sources |
||||
extern "C" IMAGE_DOS_HEADER __ImageBase; |
||||
#endif |
||||
|
||||
HMODULE GetCurrentModule() |
||||
{ |
||||
#if _MSC_VER < 1300 // earlier than .NET compiler (VC 6.0) |
||||
// Here's a trick that will get you the handle of the module |
||||
// you're running in without any a-priori knowledge: |
||||
// http://www.dotnet247.com/247reference/msgs/13/65259.aspx |
||||
|
||||
MEMORY_BASIC_INFORMATION mbi; |
||||
static int dummy; |
||||
VirtualQuery(&dummy, &mbi, sizeof(mbi)); |
||||
|
||||
return reinterpret_cast<HMODULE>(mbi.AllocationBase); |
||||
|
||||
#else // VC 7.0 |
||||
// from ATL 7.0 sources |
||||
|
||||
return reinterpret_cast<HMODULE>(&__ImageBase); |
||||
#endif |
||||
} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
参考链接: |
||||
|
||||
- https://blogs.msdn.microsoft.com/oldnewthing/20041025-00/?p=37483/ |
||||
- http://www.codeguru.com/Cpp/W-P/dll/tips/article.php/c3635/ |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
--- |
||||
title: 在vps上搭建hexo |
||||
date: 2017-12-20 21:25:57 |
||||
tags: [vps, hexo] |
||||
categories: vps |
||||
--- |
||||
|
||||
本文记录在[vps](https://www.vultr.com/?ref=7276933)上搭建hexo的过程。 |
||||
|
||||
<!-- more --> |
||||
|
||||
在vps上搭建hexo,网络上已经有不少教程了,但是全部套路都是一样,大致流程如下: |
||||
|
||||
> 本地搭建hexo环境 -> 配置hexo主题等 -> 本地编写md文件 -> 通过hexo d进行远程部署 |
||||
|
||||
这样的流程,有个最大的问题是,远程服务器只保存了最终渲染完成的html文件,每次更换电脑都需要重新部署环境,所以我就把hexo部署到了远程vps上,本地编写md,然后提交到远程git,由git的hook功能触发hexo进行渲染和部署,大致流程如下: |
||||
|
||||
> 本地编写md -> 提交到vps上的git-repo -> post-receive -> hexo generate -> hexo deploy -> nginx |
||||
|
||||
在远程仓库的hooks目录,创建post-receive文件,在这里进行hexo的渲染和部署: |
||||
|
||||
```shell |
||||
#! /bin/bash |
||||
|
||||
git --work-tree=/home/lniwn/hexo/source/ --git-dir=/home/git/repo/blog.git/ checkout -f |
||||
hexo --cwd /home/lniwn/hexo/ clean |
||||
hexo --cwd /home/lniwn/hexo/ g -d |
||||
cp -Rf /home/lniwnxxx/hexo/public/* /var/www/oaoa.me/ |
||||
``` |
||||
|
||||
这样可以在任何地方编写md文件,写完之后通过git提交即可看到自动部署的信息 |
||||
{% asset_img TortoiseGit-message.png TortoiseGit打印的远程部署信息 %} |
||||
|
||||
由于我创建了一个git用户,仅用于git相关操作,而我的登陆用户是lniwn,部署时经常会遇到权限问题,所以需要进行一些权限分配: |
||||
|
||||
- 将lniwn添加到git组 `$ sudo usermod -a -G git lniwn` |
||||
- 修改hexo文件夹所属组 `$ sudo chgrp git -R /home/lniwn/hexo/` |
||||
- 修改hexo文件夹组权限 `$ sudo chmod g+rw -R /home/lniwn/hexo/` |
||||
|
||||
虽然每次git的push操作都会触发post-receive,从而进行自动部署,但是有时候还是希望手动部署下,所以写了个部署脚本auto-deploy-hexo,脚本很简单,就是以git用户执行post-receive文件: |
||||
|
||||
```shell |
||||
#! /bin/bash |
||||
|
||||
sudo -H -u git bash -c '/home/git/repo/blog.git/hooks/post-receive' |
||||
``` |
||||
@ -0,0 +1,478 @@
@@ -0,0 +1,478 @@
|
||||
--- |
||||
title: 《流畅的Python》学习笔记 |
||||
date: 2018-10-09 19:48:53 |
||||
tags: [python] |
||||
categories: python |
||||
--- |
||||
《流畅的Python》学习笔记,备忘录形式。 |
||||
<!-- more --> |
||||
|
||||
## 第1章 Python数据模型 |
||||
|
||||
## 第2章 序列构成的数组 |
||||
|
||||
### 一个关于+=的谜题 |
||||
|
||||
`+=`对应的方法为`__iadd__`,对应的指令为`INPLACE_ADD`,表示`inplace add`。对应实现了`__iadd__`的对象,解释器会直接调用该方法,否则退化为调用`__add__`,然后再赋值。 |
||||
```python |
||||
>>> t=(1,2,[30,50]) |
||||
>>> t[2] += [50,60] |
||||
Traceback (most recent call last): |
||||
File "<stdin>", line 1, in <module> |
||||
TypeError: 'tuple' object does not support item assignment |
||||
>>> t |
||||
(1, 2, [30, 50, 50, 60]) |
||||
``` |
||||
通过上面的代码,我们发现:`t[2] += [50,60]`抛出异常,但是`t`的值仍然被改变了,通过字节码来分析执行过程: |
||||
```python |
||||
>>> t=(1,2,[30,50]) |
||||
>>> dis.dis('t[2] += [50,60]') |
||||
1 0 LOAD_NAME 0 (t) |
||||
2 LOAD_CONST 0 (2) |
||||
4 DUP_TOP_TWO |
||||
6 BINARY_SUBSCR |
||||
8 LOAD_CONST 1 (50) |
||||
10 LOAD_CONST 2 (60) |
||||
12 BUILD_LIST 2 |
||||
14 INPLACE_ADD |
||||
16 ROT_THREE |
||||
18 STORE_SUBSCR |
||||
20 LOAD_CONST 3 (None) |
||||
22 RETURN_VALUE |
||||
``` |
||||
`18 STORE_SUBSCR`执行失败,因为`t`是个不可变对象。 |
||||
三个点: |
||||
- 不要把可变对象(列表)放在不可变对象(元组)中; |
||||
- 增量赋值不是原子操作; |
||||
- 多查看Python的字节码,来分析背后的运行机制。 |
||||
|
||||
## 第3章 字典和集合 |
||||
|
||||
### 子类化UserDict |
||||
|
||||
创造自定义映射类型,优先使用`collections.UserDict`为基类,而不是以`dict`为基类。`UserDict`有个属性叫做`data`,是`dict`的实例,这个属性实际上是`UserDict`最终存储数据的地方。 |
||||
|
||||
### 不可变映射类型 |
||||
|
||||
标准库里所有的映射类型都是可变的,如果希望构造一个不可变的映射,可以使用[`MappingProxyType`](https://docs.python.org/3/library/types.html#types.MappingProxyType),给这个类一个映射,它会返回一个只读的映射视图。 |
||||
|
||||
### 集合字面量 |
||||
|
||||
构造空集合,需要写成`set()`的形式,`{}`表示构造空字典。使用字面量构造集合比使用构造函数的形式要快,因为从字面量构造时,Python会利用一个专门的字节码`BUILD_SET`来创建集合。 |
||||
|
||||
```python |
||||
>>> dis.dis('{1}') |
||||
1 0 LOAD_CONST 0 (1) |
||||
2 BUILD_SET 1 |
||||
4 RETURN_VALUE |
||||
>>> dis.dis('set([1])') |
||||
1 0 LOAD_NAME 0 (set) |
||||
2 LOAD_CONST 0 (1) |
||||
4 BUILD_LIST 1 |
||||
6 CALL_FUNCTION 1 |
||||
8 RETURN_VALUE |
||||
``` |
||||
|
||||
## 第4章 文本和字节序列 |
||||
|
||||
### 默认编码值 |
||||
|
||||
- 如果打开文件时没有指定`encoding`参数,默认值由`locale.getpreferredencoding()`提供。 |
||||
|
||||
- 如果设定了`PYTHONIOENCODING`环境变量,`sys.stdout/stdin.stderr`的编码使用设定的值,否则继承自所在控制台,如果输入/输出重定向到文件,则由`locale.getpreferredencoding()`定义。 |
||||
|
||||
*在Python3.6以后,Windows平台下,指定`PYTHONIOENCODING`的同时还需要指定[`PYTHONLEGACYWINDOWSSTDIO`](https://docs.python.org/3/using/cmdline.html#envvar-PYTHONLEGACYWINDOWSSTDIO)才能让`sys.stdout/stdin/stderr`使用指定编码*。 |
||||
|
||||
- Python在二进制数据和字符串之间转换时,内部使用`sys.getdefaultencoding()`获得的编码(在Python3中无法被修改)。 |
||||
|
||||
- `sys.getfilesystemencoding()`用于编解码文件名(不是文件内容)。把字符串参数作为文件名传给`open()`函数时就会使用它,如果传入的文件名参数是字节序列,那就不经改动直接传给OS API。可参考[Unicode filenames](https://docs.python.org/3/howto/unicode.html#unicode-filenames)一文。 |
||||
|
||||
## 第5章 一等函数 |
||||
|
||||
### 高阶函数 |
||||
|
||||
接受函数为参数,或者把函数作为结果返回的函数是`高阶函数(higher-order function)`。 |
||||
|
||||
### 可调用对象 |
||||
|
||||
如果想判断对象能否调用,可以使用内置的`callable()`函数。Python数据模型文档列出了7中可调用对象。 |
||||
|
||||
- 用户定义的函数 |
||||
|
||||
使用def语句或lambda表达式创建。 |
||||
|
||||
- 内置函数 |
||||
|
||||
使用C语言(CPython)实现的函数,如`len`或`time.strftime`。 |
||||
|
||||
- 内置方法 |
||||
|
||||
使用C语言实现的方法,如`dict.get`。 |
||||
|
||||
- 方法 |
||||
|
||||
在类的定义体中定义的函数。 |
||||
|
||||
- 类 |
||||
|
||||
调用类时会运行类的`__new__`方法创建一个实例,然后运行`__init__`方法,初始化实例,最后把实例返回给调用方。因为Python没有new运算符,所以调用类相当于调用函数。 |
||||
|
||||
- 类的实例 |
||||
|
||||
如果类定义了`__call__`方法,那么它的实例可以作为函数调用。 |
||||
|
||||
- 生成器函数 |
||||
|
||||
使用`yield`关键字的函数或方法。调用生成器函数返回的是生成器对象。 |
||||
|
||||
### 获取关于参数的信息 |
||||
|
||||
函数对象有个`__defaults__`属性,它的值是一个元组,里面保存着定位参数和关键字参数的默认值。仅限关键字参数的默认值在`__kwdefaults__`属性中。然而,参数的名称在`__code__`属性中,它的值是一个`code`对象引用,自身也有很多属性。 |
||||
|
||||
使用`inspect`模块提取函数签名,`inspect.Parameter.kind`值有以下5中: |
||||
|
||||
- `POSITIONAL_OR_KEYWORD` |
||||
|
||||
可以通过定位参数和关键字传入的形参(多数Python函数的参数属于此类)。 |
||||
|
||||
- `VAR_POSITIONAL` |
||||
|
||||
定位参数元组。 |
||||
|
||||
- `VAR_KEYWORD` |
||||
|
||||
关键字参数字典。 |
||||
|
||||
- `KEYWORD_ONLY` |
||||
|
||||
仅限关键字参数(Python3新增)。 |
||||
|
||||
- `POSITIONAL_ONLY` |
||||
|
||||
仅限定位参数。目前,Python声明函数的语法不支持,但是有些使用C语言实现且不接受关键字参数的函数(如divmod)支持。 |
||||
|
||||
### 函数注解 |
||||
|
||||
Python3提供了一种句法,用于为函数声明中的参数和返回值附加元数据。 |
||||
|
||||
```python |
||||
def clip(text: str, max_len: 'int > 0'=80) -> str: |
||||
""" |
||||
在max_len前面或后面的第一个空格处截断文本 |
||||
""" |
||||
return text |
||||
``` |
||||
|
||||
函数声明中的各个参数可以在`:`之后附加注解表达式。如果参数有默认值,注解放在参数名和`=`之间。如果想注解返回值,在`)`和函数声明末尾的`:`之间添加`->`和一个表达式。那个表达式可以是任何类型。 |
||||
|
||||
注解不会做任何处理,只是存储在函数的`__annotations__`属性中。 |
||||
|
||||
Python对注解所做的唯一的事情是,把它们存储在函数的`__annotations__`属性里,解释器不会对注解做任何处理或验证。注解只是元数据,可供IDE、框架和装饰器等工具使用。可以使用`inspect.signature()`函数提取注解。 |
||||
|
||||
## 第6章 使用一等函数实现设计模式 |
||||
|
||||
### 案例分析:重构“策略”模式 |
||||
|
||||
在Python中,模块也是一等对象,而且标准库提供了几个处理模块的函数。 |
||||
|
||||
`globals()`返回一个字典,表示当前的全局符号表。这个符号表始终针对当前模块(对函数或方法来说,是指定义他们的模块,而不是调用他们的模块)。 |
||||
|
||||
`inspect.getmembers`函数用于获取对象的属性。 |
||||
|
||||
## 第7章 函数装饰器和闭包 |
||||
|
||||
### 装饰器基础知识 |
||||
|
||||
装饰器是可调用对象,其参数是另一个函数(被装饰的函数)。装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或者可调用对象。 |
||||
|
||||
假如有个名为`decorate`的装饰器 |
||||
|
||||
```python |
||||
@decorate |
||||
def target(): |
||||
print('running target()') |
||||
``` |
||||
|
||||
上述代码的效果与下述写法一致: |
||||
|
||||
```python |
||||
def target(): |
||||
print('running target()') |
||||
target = decorate(target) |
||||
``` |
||||
|
||||
装饰器只是语法糖,有两大特性: |
||||
|
||||
- 能把被装饰的函数替换成其他函数。 |
||||
- 装饰器在加载模块时立即执行。 |
||||
|
||||
### Python何时执行装饰器 |
||||
|
||||
函数装饰器在**导入**模块时(被装饰函数定义时)立即执行,而被装饰的函数只在明确**调用**时运行。 |
||||
|
||||
### 变量作用域规则 |
||||
|
||||
```python |
||||
b = 6 |
||||
def f2(a): |
||||
print(a) |
||||
print(b) |
||||
b = 9 |
||||
f2(3) |
||||
``` |
||||
|
||||
上述代码,执行会报错: |
||||
|
||||
> Traceback (most recent call last): |
||||
> |
||||
> File "<stdin>", line 1, in <module> |
||||
> |
||||
> File "<stdin>", line 3, in f2 |
||||
> |
||||
> UnboundLocalError: local variable 'b' referenced before assignment |
||||
|
||||
Python在编译函数的定义体时,它判断`b`是局部变量,因为在函数中给它赋值了。 |
||||
|
||||
这不是缺陷,而是设计选择:**Python不要求声明变量,但是假定在函数定义体中赋值的变量是局部变量**。如果在函数中赋值时想让解释器把`b`当成全局变量,要使用`global`声明。 |
||||
|
||||
### 闭包 |
||||
|
||||
闭包指延伸了作用域的函数,其中包含函数定义体中引用、但是不在定义体中定义的非全局变量。函数是不是匿名的没有关系,关键是它能访问定义体之外定义的非全局变量。 |
||||
|
||||
示例 average_oo.py: |
||||
|
||||
计算移动平均值的类 |
||||
|
||||
```python |
||||
class Averager(): |
||||
def __init__(self): |
||||
self.series = [] |
||||
|
||||
def __call__(self, new_value): |
||||
self.series.append(new_value) |
||||
total = sum(self.series) |
||||
return total/len(self.series) |
||||
|
||||
avg = Averager() |
||||
avg(10) |
||||
avg(11) |
||||
``` |
||||
|
||||
计算移动平均值的高阶函数 |
||||
|
||||
```python |
||||
def make_averager(): |
||||
series = [] |
||||
|
||||
def averager(new_value): |
||||
series.append(new_value) |
||||
total = sum(self.series) |
||||
return total/len(self.series) |
||||
|
||||
return averager |
||||
|
||||
avg = make_averager() |
||||
avg(10) |
||||
avg(11) |
||||
``` |
||||
|
||||
在`averager`函数中,`series`是**自由变量(free variable)**。这是一个技术术语,指未在本地作用域中绑定的变量。 |
||||
|
||||
{% asset_img frame7-1.png 自由变量 %} |
||||
|
||||
综上,闭包是一种函数,它会保留定义函数时存在的自由变量的绑定,这样调用函数时,虽然定义作用域不可用了,但是仍然能使用那些绑定。 |
||||
|
||||
### nonlocal声明 |
||||
|
||||
用于在闭包中声明变量作用域。 |
||||
|
||||
### 标准库中的装饰器 |
||||
|
||||
`functools.lru_cache`实现了备忘(memorization)功能。这是一项优化技术,它把耗时的函数的结果保存起来,避免传入相同的参数时重复计算。可用来优化递归调用。因为`lru_cache`使用字典存储结果,而且键根据调用时传入的定位参数和关键字参数创建,所以被`lru_cache`装饰的函数,它的所有参数都必须是**可散列的**。 |
||||
|
||||
`functools.singledispatch`可以使普通的函数变为泛函数(generic function):根据第一个参数的类型,以不同方式执行相同操作的一组函数。`singledispatch`机制的一个显著特征是,你可以在系统的任何地方和任何模块中注册专门函数。如果后来在新的模块中定义了新的类型,可以轻松地添加一个新的专门函数来处理那个类型。此外,你还可以为不是自己编写的或者不能修改的类添加自定义函数。 |
||||
|
||||
### 参数化装饰器 |
||||
|
||||
创建一个装饰器工厂函数,把参数传给它,返回一个装饰器,然后再把它应用到要装饰的函数上。 |
||||
|
||||
```python |
||||
from inspect import signature |
||||
from functools import wraps |
||||
|
||||
def typeassert(*ty_args, **ty_kwargs): |
||||
def decorate(func): |
||||
# If in optimized mode, disable type checking |
||||
if not __debug__: |
||||
return func |
||||
|
||||
# Map function argument names to supplied types |
||||
sig = signature(func) |
||||
bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments |
||||
|
||||
@wraps(func) |
||||
def wrapper(*args, **kwargs): |
||||
bound_values = sig.bind(*args, **kwargs) |
||||
# Enforce type assertions across supplied arguments |
||||
for name, value in bound_values.arguments.items(): |
||||
if name in bound_types: |
||||
if not isinstance(value, bound_types[name]): |
||||
raise TypeError( |
||||
'Argument {} must be {}'.format(name, bound_types[name]) |
||||
) |
||||
return func(*args, **kwargs) |
||||
return wrapper |
||||
return decorate |
||||
``` |
||||
|
||||
```python |
||||
import types |
||||
from functools import wraps |
||||
|
||||
class Profiled: |
||||
def __init__(self, func): |
||||
wraps(func)(self) |
||||
self.ncalls = 0 |
||||
|
||||
def __call__(self, *args, **kwargs): |
||||
self.ncalls += 1 |
||||
return self.__wrapped__(*args, **kwargs) |
||||
|
||||
def __get__(self, instance, cls): |
||||
if instance is None: |
||||
return self |
||||
else: |
||||
return types.MethodType(self, instance) |
||||
``` |
||||
|
||||
{% cq %} *示例来自[python3-cookbook](https://python3-cookbook.readthedocs.io/zh_CN/latest/chapters/p09_meta_programming.html)*{% endcq %} |
||||
|
||||
## 第8章 对象引用、可变性和垃圾回收 |
||||
|
||||
### 在`==`和`is`之间选择 |
||||
|
||||
`==`比较是两个变量的值是否相等,`is`比较两个变量是否同一个对象,即对象标识是否相等。 |
||||
|
||||
`is`运算符比`==`速度快,因为它不能重载,所以Python不用寻找并调用特殊方法,而是直接比较两个整数ID。 |
||||
|
||||
### 默认做浅复制 |
||||
```python |
||||
l1 = [3, [66, 55, 44], (7, 8, 9)] |
||||
l2 = list(l1) # l2是l1的浅复制副本 |
||||
l1.append(100) # 把100追加到l1中,对l2没有影响 |
||||
l1[1].remove(55) # 对l2有影响,因为l2[1]绑定的列表与l1[1]是同一个 |
||||
print('l1:', l1) # l1: [3, [66, 44], (7, 8, 9), 100] |
||||
print('l2:', l2) # l2: [3, [66, 44], (7, 8, 9)] |
||||
l2[1] += [33, 22] # 对可变对象来说,如l2[1]引用的列表,+=运算符就地修改列表。这次修改在l1[1]中也有提现 |
||||
l2[2] += (10, 11) # 对元组来说,+=运算符创建一个新元组,然后新绑定给变量l2[2]。现在l2和l1最后位置上的元组不是同一个对象。 |
||||
print('l1:', l1) # l1: [3, [66, 44, 33, 22], (7, 8, 9), 100] |
||||
print('l2:', l2) # l2: [3, [66, 44, 33, 22], (7, 8, 9, 10, 11)] |
||||
``` |
||||
|
||||
### 函数的参数作为引用时 |
||||
|
||||
函数可选参数的默认值在定义函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性。因此,如果默认值是可变对象,而且修改了它的值,那么后续的函数调用都会受到影响。 |
||||
|
||||
### del和垃圾回收 |
||||
|
||||
CPython主要使用引用计数进行内存管理,CPython2.0增加了分代垃圾回收算法,用于检测循环引用的问题。 |
||||
|
||||
del不会删除对象,但是执行del后,可能会导致对象不可获取,从而被GC删除。 |
||||
|
||||
### 弱引用 |
||||
|
||||
`weakref`模块的[文档](https://docs.python.org/3/library/weakref.html)指出,`weakref.ref`类其实是底层接口,供高级用途使用,多数程序最好使用`weakref`集合和`finalize`。也就是说,应该使用`WeakKeyDictonary`、`WeakValueDictionary`、`WeakSet`和`finalize`,不要自己动手创建并处理`weakref.ref`实例。 |
||||
|
||||
## 第9章 符合Python风格的对象 |
||||
|
||||
### Python的私有属性和“受保护的”属性 |
||||
|
||||
以两个前导下划线开头,尾部没有或最多有一个下划线的实例属性,Python会把属性名存入实例的`__dict__`属性中,而且会在前面加上一个下划线和类名,这个语言特性叫做**名称改写**(name mangling)。 |
||||
以单个下划线开头的实例属性,表示“受保护的”属性,但是仍然可以直接访问到。 |
||||
|
||||
### 使用`__slots__`类属性节省空间 |
||||
|
||||
默认情况下,Python在各个实例中名为`__dict__`的字典里存储实例属性。为了使用底层的散列表提升访问速度,字典会消耗大量内存。如果要处理数百万个属性不多的实例,通过`__slots__`类属性,能节省大量内存,方法是让解释器在元组中存储实例属性,而不用字典。 |
||||
继承自超类的`__slots__`属性没有效果。Python只会使用各个类中定义的`__slots__`属性。 |
||||
定义`__slots__`的方式是,创建一个类属性,使用`__slots__`这个名字,并把它的值设为一个字符串构成的可迭代对象,其中各个元素表示各个实例属性。 |
||||
不要在`__slots__`中添加`__dict__`,这样做违背了设计初衷。 |
||||
为了让对象支持弱引用,必须有`__weakref__`属性。用户定义的类默认就有`__weakref__`属性,可是,如果类中定义了`__slots__`属性,而且想把实例作为弱引用的目标,那么要手动把`__weakref__`添加到`__slots__`中。 |
||||
几个注意点: |
||||
- 每个子类都要定义`__slots__`属性,因为解释器会忽略继承的`__slots__`属性。 |
||||
- 实例只能拥有`__slots__`中列出的属性,除非把`__dict__`加入`__slots__`中(这样做就失去了节省内存的功效)。 |
||||
- 如果不把`__weakref__`加入`__slots__`,实例就不能作为弱引用的目标。 |
||||
|
||||
## 第10章 序列的修改、散列和切片 |
||||
|
||||
### 协议和鸭子类型 |
||||
Python的序列协议只需要`__len__`和`__getitem__`两个方法。任何类,只要使用标准的签名和语义实现了这两个方法,就能用在任何期待序列的地方。人们称其为**鸭子类型**(duck typing)。 |
||||
|
||||
### 切片原理 |
||||
`slice.indices(len) -> (start, stop, stride)` |
||||
`all`, `functools.reduce`, `zip`, `reprlib` |
||||
|
||||
## 第11章 接口:从协议到抽象基类 |
||||
协议是接口,但不是正式的(只由文档和约定定义),因此协议不能像正式接口那样施加限制。 |
||||
|
||||
### 标准库中的抽象基类 |
||||
[Collections Abstract Base Classes](https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes) |
||||
- `abc` |
||||
- `collections.abc` |
||||
- `numbers` |
||||
|
||||
### 定义并使用一个抽象基类 |
||||
在Python 3.4及以上版本,可以直接继承自`abc.ABC`,在旧版本中,需要在class语句中使用`metaclass`关键字,把值设为`abc.ABCMeta`。 |
||||
```python python3的写法 |
||||
class Tombola(metaclass=abc.ABCMeta): # python3 |
||||
pass |
||||
``` |
||||
```python python2的写法 |
||||
class Tombola(object): # python2 |
||||
__metaclass__ = abc.ABCMeta |
||||
``` |
||||
[`@abc.abstractmethod`](https://docs.python.org/3/library/abc.html#abc.abstractmethod)装饰器可以堆叠,但是与其他装饰器合用时,该装饰器必须位于最里层。 |
||||
白鹅类型的一个基本特性:即便不继承,也有办法把一个类注册为抽象基类的**虚拟子类**。注册虚拟子类的方式是在抽象基类上调用`register`方法。这么做之后,注册的类会变成抽象基类的虚拟子类,而且`issubclass`和`isinstance`等函数都能识别,但是注册的类不会从抽象基类中继承任何方法或属性。Python不会对注册类的实现做检查,如果有接口未实现,只能通过运行时错误发现。Python3.3之后的版本,`register`方法可以当做装饰器使用。 |
||||
类的继承关系在一个特殊的类属性中指定`__mro__`,即方法解析顺序(Method Resolution Order)。这个属性的作用很简单,按顺序列出类及其超类,Python会按照这个顺序搜索方法。通过`register`方法注册的类,不在`__mro__`列表中。 |
||||
|
||||
### 鹅的行为有可能像鸭子 |
||||
`__subclasshook__`在白鹅类型中添加了一些鸭子类型的踪迹。我们可以使用抽象基类定义正式接口,可以始终使用`isinstance`检查,也可以完全使用不相关的类,只要实现特定的方法即可。只有提供`__subclasshook__`方法的抽象基类才能这么做。 |
||||
|
||||
## 第12章 继承的优缺点 |
||||
### 子类化内置类型很麻烦 |
||||
直接子类化内置类型(如`dict`, `list`或`str`)容易出错,因为内置类型的方法通常会忽略用户覆盖的方法。不要子类化内置类型,用户自定义的类应该继承`collections`模块中的类,例如`UserDict`、`UserList`和`UserString`,这些类做了特殊处理,因此易于扩展。 |
||||
|
||||
### 处理多重继承 |
||||
1. 把接口继承和实现继承区分开 |
||||
使用多重继承时,一定要明确一开始为什么创建子类。主要原因可能有: |
||||
- 继承接口,创建子类型,实现“是什么”关系 |
||||
- 继承实现,通过重用避免代码重复 |
||||
2. 使用抽象基类显示表示接口 |
||||
现代的Python中,如果类的作用是定义接口,应该明确把它定义为抽象基类,创建`abc.ABC`或其他抽象基类的子类 |
||||
3. 通过混入重用代码 |
||||
如果一个类的作用是为多个不相关的子类提供方法实现,从而实现方法重用,但不体现“是什么”关系,应该把那个类明确定义为**混入类(mixin class)** |
||||
4. 在名称中明确指明混入 |
||||
因为在Python中没有把类声明为混入的正规方式,所以强烈推荐名称中加入...Mixin后缀 |
||||
5. 抽象基类可以作为混入,反过来则不成立 |
||||
抽象基类可以实现具体方法,因此可以作为混入使用。不过,抽象基类会定义类型,而混入做不到。 |
||||
6. 不要子类化多个具体类 |
||||
具体类可以没有,或最多只有一个具体超类。也就是说,具体类的超类中除了这一个具体超类之外,其余的都是抽象基类或混入。 |
||||
7. 为用户提供聚合类 |
||||
如果抽象基类或混入的组合对客户代码非常有用,那就提供一个类,使用易于理解的方式把它们组合起来。这种类叫做**聚合类(aggregate class)** |
||||
8. 优先使用对象组合,而不是类继承 |
||||
|
||||
## 第13章 正确重载运算符 |
||||
### 运算符重载基础 |
||||
- 不能重载内置类型的运算符 |
||||
- 不能新建运算符,只能重载现有的 |
||||
- 某些运算符不能重载--`is`、`and`、`or`和`not`(不过位运算符`&|~`可以) |
||||
|
||||
### 重载向量加法运算符+ |
||||
实现一元运算符和中缀运算符的特殊方法一定不能修改操作数。使用这些运算符的表达式期待结果是新对象。 |
||||
|
||||
`__add__`, `__radd__`, `__iadd__` |
||||
|
||||
{% asset_img frame13-1.png %} |
||||
|
||||
### 众多比较运算符 |
||||
- 正向和反向调用使用的是同一系列方法。 |
||||
- 对`==`和`!=`来说,如果反向调用失败,Python会比较对象的ID,而不抛出`TypeError`。 |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
--- |
||||
title: 解决chromium警告C4819 |
||||
date: 2018-04-26 20:57:04 |
||||
tags: [chromium] |
||||
categories: chromium |
||||
--- |
||||
|
||||
初次构建chromium的时候,可能会遇到错误 |
||||
> : warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss |
||||
> |
||||
> : error C2220: warning treated as error - no 'object' file generated |
||||
|
||||
<!-- more --> |
||||
|
||||
尤其是在Windows上构建的时候,更容易遇到,网络上的方法,基本都是修改系统区域为英国(美国): |
||||
|
||||
> 控制面板--区域--管理--更改系统区域设置 |
||||
> 在页面中选择英语区域即可 |
||||
|
||||
~~这样修改系统设置,我不太喜欢,尤其是在工作机上,这样修改可能会引起其他未知问题,所以直接修改了[gn配置文件](https://chromium.googlesource.com/chromium/src.git/+/master/build/config/compiler/BUILD.gn#1161)中的`default_warnings`字段,添加一项`"/wd4819"`即可。~~ |
||||
|
||||
--- |
||||
|
||||
**Update:** |
||||
|
||||
上面方法会导致部分文件无法正常解析,产生各种奇怪的语法错误。 |
||||
|
||||
新版chromium已经修复了此问题,提交详情见[这里](https://chromium.googlesource.com/chromium/src.git/+/663994ebf90ac57f5cc56a9639a16e29aee1ff2b%5E%21/#F0),最新的BUILD.gn文件见[这里](https://chromium.googlesource.com/chromium/src.git/+/663994ebf90ac57f5cc56a9639a16e29aee1ff2b/build/config/compiler/BUILD.gn#842),其基本原理就是VS2015支持的新特性[/utf-8](https://msdn.microsoft.com/en-us/library/mt708821.aspx),所以最终只需要在`build/config/compiler/BUILD.gn`文件中添加该编译选项即可: |
||||
|
||||
```gn |
||||
cflags += [ |
||||
# Assume UTF-8 by default to avoid code page dependencies. |
||||
"/utf-8", |
||||
] |
||||
``` |
||||
|
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
{"Target":"bundle.min.9e52e68b082cf2a30a7fead88260edb8818fbd7f7831e39674917d4539ec75df41ba88eaddfbd916594ab4fb2a31913b46cf2d6094cf80381edb8c632512a8ca.js","MediaType":"application/javascript","Data":{"Integrity":"sha512-nlLmiwgs8qMKf+rYgmDtuIGPvX94MeOWdJF9RTnsdd9Buojq3fvZFllKtPsqMZE7Rs8tYJTPgDge24xjJRKoyg=="}} |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
const throttle=(callback,limit)=>{let timeoutHandler=null;return()=>{if(timeoutHandler==null){timeoutHandler=setTimeout(()=>{callback();timeoutHandler=null;},limit);}};};const listen=(ele,e,callback)=>{if(document.querySelector(ele)!==null){document.querySelector(ele).addEventListener(e,callback);}} |
||||
let header=document.getElementById('site-header');let lastScrollPosition=window.pageYOffset;const autoHideHeader=()=>{let currentScrollPosition=Math.max(window.pageYOffset,0);if(currentScrollPosition>lastScrollPosition){header.classList.remove('slideInUp');header.classList.add('slideOutDown');}else{header.classList.remove('slideOutDown');header.classList.add('slideInUp');} |
||||
lastScrollPosition=currentScrollPosition;} |
||||
let mobileMenuVisible=false;const toggleMobileMenu=()=>{let mobileMenu=document.getElementById('mobile-menu');if(mobileMenuVisible==false){mobileMenu.style.animationName='bounceInRight';mobileMenu.style.webkitAnimationName='bounceInRight';mobileMenu.style.display='block';mobileMenuVisible=true;}else{mobileMenu.style.animationName='bounceOutRight';mobileMenu.style.webkitAnimationName='bounceOutRight' |
||||
mobileMenuVisible=false;}} |
||||
const showImg=()=>{document.querySelector('.bg-img').classList.add('show-bg-img');} |
||||
const hideImg=()=>{document.querySelector('.bg-img').classList.remove('show-bg-img');} |
||||
const toggleToc=()=>{document.getElementById('toc').classList.toggle('show-toc');} |
||||
if(header!==null){listen('#menu-btn',"click",toggleMobileMenu);listen('#toc-btn',"click",toggleToc);listen('#img-btn',"click",showImg);listen('.bg-img',"click",hideImg);document.querySelectorAll('.post-year').forEach((ele)=>{ele.addEventListener('click',()=>{window.location.hash='#'+ele.id;});});window.addEventListener('scroll',throttle(()=>{autoHideHeader();if(mobileMenuVisible==true){toggleMobileMenu();}},250));} |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
{"Target":"js/main.min.35ccbf1cdceb91e4c64c06b5d009d6e2977fafe56beda7762febd4e67528d2ac.js","MediaType":"application/javascript","Data":{"Integrity":"sha256-Ncy/HNzrkeTGTAa10AnW4pd/r+Vr7ad2L+vU5nUo0qw="}} |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
{"Target":"main.min.0d47b4686e972122bd29f0c1e3dd024a2d541cd8b1b543622520822ea6f4238a.css","MediaType":"text/css","Data":{"Integrity":"sha256-DUe0aG6XISK9KfDB490CSi1UHNixtUNiJSCCLqb0I4o="}} |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
{"Target":"css/style.min.568c54a56780af2a70c45272522247710b69dbfc080b315211fb98381e3796f8.css","MediaType":"text/css","Data":{"Integrity":"sha256-VoxUpWeArypwxFJyUiJHcQtp2/wICzFSEfuYOB43lvg="}} |
||||
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<browserconfig> |
||||
<msapplication> |
||||
<tile> |
||||
<square150x150logo src="/mstile-150x150.png"/> |
||||
<TileColor>#da532c</TileColor> |
||||
</tile> |
||||
</msapplication> |
||||
</browserconfig> |
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
{ |
||||
"name": "", |
||||
"short_name": "", |
||||
"icons": [ |
||||
{ |
||||
"src": "/android-chrome-192x192.png", |
||||
"sizes": "192x192", |
||||
"type": "image/png" |
||||
}, |
||||
{ |
||||
"src": "/android-chrome-512x512.png", |
||||
"sizes": "512x512", |
||||
"type": "image/png" |
||||
} |
||||
], |
||||
"theme_color": "#ffffff", |
||||
"background_color": "#ffffff", |
||||
"display": "standalone" |
||||
} |
||||