关于缩进的 Sublime 文本排序
Sublime Text Sorting with Respect to Indentation
我正在寻找 Sublime Text 插件或任何一种可以按字母顺序排序但尊重缩进的程序。
例如,
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
将按函数名称排序。
在 Sublime Text 中使用默认排序会导致:
"/api/beats/by_user/#{userId}"
"/api/feedbacks"
"/api/send_mass_message"
"/api/send_message/#{userId}"
beatsByUserPath: (userId) ->
feedbackCreatePath: ->
sendMassMessagePath: ->
sendMessagePath: (userId) ->
这是我要排序的完整文件。
RouteHelper =
EXTERNAL:
soundcloudConvertPath: (url) ->
url = encodeURIComponent(url)
"http://streampocket.com/?stream=#{url}"
youtubeConvertPath: (url) ->
url = encodeURIComponent(url)
"http://www.video2mp3.net/loading.php?url=#{url}"
UTIL:
imageProxy: (url) ->
url = encodeURIComponent(url)
"/image-proxy/#{url}"
API:
beatsReportPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/report"
beatsTrackDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/track_download"
beatSetDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/set_download_url"
beatsToggleVisibilityPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_visibility"
beatsToggleRecordingPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_recording"
beatsDisownPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/disown"
beatsEditNotePath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/edit_note"
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
discussPath: ->
"/api/discuss"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
feedbacksForRapPath: (arg) ->
rapId = if typeof rap is 'object' then arg.id else arg
"/api/feedbacks/feedback_for/#{rapId}"
followersPath: (userId) ->
"/api/followers/#{userId}"
followingPath: (userId) ->
"/api/following/#{userId}"
followPath: (userId) ->
"/api/follow/#{userId}"
unfollowPath: (userId) ->
"/api/unfollow/#{userId}"
propsPath: ->
"/api/props"
userBattlesPath_deprecated: (userId) ->
"/api/battles/for_user/#{userId}"
battlesLeaderboardPath: ->
"/api/battles/leaderboard"
battlesUsersWhoVotedForPath: (opts) ->
throw Error('RouteHelper: Expected ID and WHICH') if !opts.id || !opts.which
"/api/battles/#{opts.id}/users_who_voted_for/#{opts.which}"
rapProppersPath: (rapId) ->
"/api/raps/#{rapId}/proppers"
rapUntagPath: (rapId) ->
"/api/raps/#{rapId}/untag"
rapShowPath: (param) ->
if typeof param is 'object'
rapId = param.id
else rapId = param
"/api/raps/#{rapId}/show_v2"
userPinPath: ->
"/api/users/pin"
userBattlesPath: (userId) ->
"/api/users/#{userId}/battles"
userBeatsPath: (userId) ->
"/api/users/#{userId}/beats"
userRapsPath: (userId) ->
"/api/users/#{userId}/raps_v2"
userSetColorsPath: (userId) ->
"/api/users/#{userId}/set_colors"
userShowPath: (userId) ->
"/api/users/#{userId}"
usersWhoGaveProps: (userId) ->
"/api/users/#{userId}/users_who_gave_props"
userUnreadNotifCount: (userId) ->
"/api/users/#{userId}/unread_notif_count"
userRecordNetegoPath: ->
"/api/users/record_net_ego"
albumShowPath: (param) ->
param = param.slug if _.isObject(param)
"/albums/#{param}"
blueprintShowPathFromRap: (rap) ->
"/blueprints/#{rap.blueprint_id}"
battleDestroyPath: (battle) ->
"/battles/#{battle.id}"
battlesPath: ->
"/battles"
battleNewPath: ->
"/battles/new"
battleShowPath: (battle) ->
"/battles/#{battle.id}"
beatNewPath: ->
"/beats/new"
beatShowPath: (beat) ->
if typeof beat is 'number'
"/beats/#{beat}"
else if typeof beat is 'object'
if beat.slug
"/beats/#{beat.slug}"
else
"/beats/#{beat.id}"
beatTagShowPath: (beatTag) ->
"#{beatTag.slug}/instrumentals"
beatsSearchQueryPath: ->
"/beats/search_query"
beatsRecentSearchesPath: ->
"/beats/recent_searches"
cypherJudgeVotePath: ->
"/cyphers/judge-vote"
cypherJudgeShowPath: ->
"/cyphers/judge-show"
cypherSubmitPath: ->
"/cyphers/submit"
dashboardPath: ->
"/dashboard"
defaultRapThumbnailPath: ->
"/images/default_rap.png"
rhymePath: ->
"/rhyme"
contextPath: ->
"/context"
searchLyricsPath: ->
"/rap/search_lyrics"
editorSavePath: ->
"/editor/save"
editorPath: (param) ->
param = param.id if typeof param is 'object'
if param
"/editor/#{param}"
else
"/editor"
onRapSaveDialogPath: (rapId) ->
"/rap/#{rapId}/on_save_dialog"
lyricSyncSavePath: ->
"/lyric-sync/save"
lyricSyncDestroyPath: ->
"/lyric-sync/destroy"
notificationsPath: ->
"/notifications"
rapEditPath: (rap) ->
"/editor/#{rap.id}"
rapShowPath: (rap) ->
"/rap/#{rap.id}"
rapsForCypher: (cypherId) ->
"/cyphers/#{cypherId}/submissions"
isSubscribedPath: (listId) ->
"/is_subscribed/#{listId}"
subscribeToPath: (listId) ->
"/subscribe_to/#{listId}"
userShowPath: (username) ->
"/users/#{username}"
userNotificationSettingPath: ->
"/users/notification_setting"
@RouteHelper = RouteHelper
我不知道通用解决方案,因为块的定义(用于排序)高度依赖于上下文。
然而,对于您发布的具体案例,可以通过一个简单的宏通过以下步骤轻松完成:
- 将每个块合并为一行(将每次出现的
->\n
替换为 ->
)
- 单行排序
- 将每个块从一行中取消合并回原始缩进形式(将每次出现的
->
替换为 ->\n
)
唯一的问题是,Sublime 不会在宏中记录查找和替换命令。相反,我们需要安装 RegReplace
包,它提供可以记录在宏中的查找和替换命令。 (有关安装说明,请参阅 http://facelessuser.github.io/RegReplace/installation/)
安装 RegReplace
后,只需将以下两个文件放在数据目录中的 Packages/User/
下 (What is the full path to the Packages folder for Sublime text 2 on Mac OS Lion)
您现在可以通过从顶部菜单中选择 Tools -> Macros -> smart_sort
运行 smart_sort
。
免责声明:如果每个函数的缩进超过 1 行,则需要相应地调整正则表达式定义。
smart_sort.sublime-macro
(宏)
[
{
"args":
{
"replacements":
[
"merge_block_into_a_line"
]
},
"command": "reg_replace"
},
{
"args":
{
"case_sensitive": false
},
"command": "sort_lines"
},
{
"args":
{
"replacements":
[
"restore_block"
]
},
"command": "reg_replace"
}
]
reg_replace.sublime-settings
(reg_replace 定义)
{
"replacements": {
"merge_block_into_a_line": {
"find": "->\n",
"replace": "->",
"greedy": true,
"case": true
},
"restore_block": {
"find": "->",
"replace": "->\n",
"greedy": true,
"case": true
}
}
}
在看到带有完整文件示例的更新问题后,我继续创建了一个带有一些基本选项的 Sublime Text 插件来控制排序。
- 从 Package Control 安装
IndentRespectfulSort
(有关说明,请参阅 https://packagecontrol.io/packages/Indent%20Respectful%20Sort)。
- 通过
Ctrl + `
或Cmd(⌘) + `
(OSX)打开控制台。
假设您的文件像问题中那样缩进了 2 个空格,并且您只想对函数名称进行排序,请键入
view.run_command("indent_respectful_sort", {"indent": " ", "onlyDepth" : 3})
进入控制台并点击 Enter
。这将仅对函数名称进行排序,同时尊重结构的其余部分。
如果您想使用不同的选项进行排序,您可以参考插件页面https://github.com/mvnural/sublime-indent-respectful-sort以查看更多选项。
我正在寻找 Sublime Text 插件或任何一种可以按字母顺序排序但尊重缩进的程序。
例如,
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
将按函数名称排序。 在 Sublime Text 中使用默认排序会导致:
"/api/beats/by_user/#{userId}"
"/api/feedbacks"
"/api/send_mass_message"
"/api/send_message/#{userId}"
beatsByUserPath: (userId) ->
feedbackCreatePath: ->
sendMassMessagePath: ->
sendMessagePath: (userId) ->
这是我要排序的完整文件。
RouteHelper =
EXTERNAL:
soundcloudConvertPath: (url) ->
url = encodeURIComponent(url)
"http://streampocket.com/?stream=#{url}"
youtubeConvertPath: (url) ->
url = encodeURIComponent(url)
"http://www.video2mp3.net/loading.php?url=#{url}"
UTIL:
imageProxy: (url) ->
url = encodeURIComponent(url)
"/image-proxy/#{url}"
API:
beatsReportPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/report"
beatsTrackDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/track_download"
beatSetDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/set_download_url"
beatsToggleVisibilityPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_visibility"
beatsToggleRecordingPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_recording"
beatsDisownPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/disown"
beatsEditNotePath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/edit_note"
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
discussPath: ->
"/api/discuss"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
feedbacksForRapPath: (arg) ->
rapId = if typeof rap is 'object' then arg.id else arg
"/api/feedbacks/feedback_for/#{rapId}"
followersPath: (userId) ->
"/api/followers/#{userId}"
followingPath: (userId) ->
"/api/following/#{userId}"
followPath: (userId) ->
"/api/follow/#{userId}"
unfollowPath: (userId) ->
"/api/unfollow/#{userId}"
propsPath: ->
"/api/props"
userBattlesPath_deprecated: (userId) ->
"/api/battles/for_user/#{userId}"
battlesLeaderboardPath: ->
"/api/battles/leaderboard"
battlesUsersWhoVotedForPath: (opts) ->
throw Error('RouteHelper: Expected ID and WHICH') if !opts.id || !opts.which
"/api/battles/#{opts.id}/users_who_voted_for/#{opts.which}"
rapProppersPath: (rapId) ->
"/api/raps/#{rapId}/proppers"
rapUntagPath: (rapId) ->
"/api/raps/#{rapId}/untag"
rapShowPath: (param) ->
if typeof param is 'object'
rapId = param.id
else rapId = param
"/api/raps/#{rapId}/show_v2"
userPinPath: ->
"/api/users/pin"
userBattlesPath: (userId) ->
"/api/users/#{userId}/battles"
userBeatsPath: (userId) ->
"/api/users/#{userId}/beats"
userRapsPath: (userId) ->
"/api/users/#{userId}/raps_v2"
userSetColorsPath: (userId) ->
"/api/users/#{userId}/set_colors"
userShowPath: (userId) ->
"/api/users/#{userId}"
usersWhoGaveProps: (userId) ->
"/api/users/#{userId}/users_who_gave_props"
userUnreadNotifCount: (userId) ->
"/api/users/#{userId}/unread_notif_count"
userRecordNetegoPath: ->
"/api/users/record_net_ego"
albumShowPath: (param) ->
param = param.slug if _.isObject(param)
"/albums/#{param}"
blueprintShowPathFromRap: (rap) ->
"/blueprints/#{rap.blueprint_id}"
battleDestroyPath: (battle) ->
"/battles/#{battle.id}"
battlesPath: ->
"/battles"
battleNewPath: ->
"/battles/new"
battleShowPath: (battle) ->
"/battles/#{battle.id}"
beatNewPath: ->
"/beats/new"
beatShowPath: (beat) ->
if typeof beat is 'number'
"/beats/#{beat}"
else if typeof beat is 'object'
if beat.slug
"/beats/#{beat.slug}"
else
"/beats/#{beat.id}"
beatTagShowPath: (beatTag) ->
"#{beatTag.slug}/instrumentals"
beatsSearchQueryPath: ->
"/beats/search_query"
beatsRecentSearchesPath: ->
"/beats/recent_searches"
cypherJudgeVotePath: ->
"/cyphers/judge-vote"
cypherJudgeShowPath: ->
"/cyphers/judge-show"
cypherSubmitPath: ->
"/cyphers/submit"
dashboardPath: ->
"/dashboard"
defaultRapThumbnailPath: ->
"/images/default_rap.png"
rhymePath: ->
"/rhyme"
contextPath: ->
"/context"
searchLyricsPath: ->
"/rap/search_lyrics"
editorSavePath: ->
"/editor/save"
editorPath: (param) ->
param = param.id if typeof param is 'object'
if param
"/editor/#{param}"
else
"/editor"
onRapSaveDialogPath: (rapId) ->
"/rap/#{rapId}/on_save_dialog"
lyricSyncSavePath: ->
"/lyric-sync/save"
lyricSyncDestroyPath: ->
"/lyric-sync/destroy"
notificationsPath: ->
"/notifications"
rapEditPath: (rap) ->
"/editor/#{rap.id}"
rapShowPath: (rap) ->
"/rap/#{rap.id}"
rapsForCypher: (cypherId) ->
"/cyphers/#{cypherId}/submissions"
isSubscribedPath: (listId) ->
"/is_subscribed/#{listId}"
subscribeToPath: (listId) ->
"/subscribe_to/#{listId}"
userShowPath: (username) ->
"/users/#{username}"
userNotificationSettingPath: ->
"/users/notification_setting"
@RouteHelper = RouteHelper
我不知道通用解决方案,因为块的定义(用于排序)高度依赖于上下文。
然而,对于您发布的具体案例,可以通过一个简单的宏通过以下步骤轻松完成:
- 将每个块合并为一行(将每次出现的
->\n
替换为->
) - 单行排序
- 将每个块从一行中取消合并回原始缩进形式(将每次出现的
->
替换为->\n
)
唯一的问题是,Sublime 不会在宏中记录查找和替换命令。相反,我们需要安装 RegReplace
包,它提供可以记录在宏中的查找和替换命令。 (有关安装说明,请参阅 http://facelessuser.github.io/RegReplace/installation/)
安装 RegReplace
后,只需将以下两个文件放在数据目录中的 Packages/User/
下 (What is the full path to the Packages folder for Sublime text 2 on Mac OS Lion)
您现在可以通过从顶部菜单中选择 Tools -> Macros -> smart_sort
运行 smart_sort
。
免责声明:如果每个函数的缩进超过 1 行,则需要相应地调整正则表达式定义。
smart_sort.sublime-macro
(宏)
[
{
"args":
{
"replacements":
[
"merge_block_into_a_line"
]
},
"command": "reg_replace"
},
{
"args":
{
"case_sensitive": false
},
"command": "sort_lines"
},
{
"args":
{
"replacements":
[
"restore_block"
]
},
"command": "reg_replace"
}
]
reg_replace.sublime-settings
(reg_replace 定义)
{
"replacements": {
"merge_block_into_a_line": {
"find": "->\n",
"replace": "->",
"greedy": true,
"case": true
},
"restore_block": {
"find": "->",
"replace": "->\n",
"greedy": true,
"case": true
}
}
}
在看到带有完整文件示例的更新问题后,我继续创建了一个带有一些基本选项的 Sublime Text 插件来控制排序。
- 从 Package Control 安装
IndentRespectfulSort
(有关说明,请参阅 https://packagecontrol.io/packages/Indent%20Respectful%20Sort)。 - 通过
Ctrl + `
或Cmd(⌘) + `
(OSX)打开控制台。 假设您的文件像问题中那样缩进了 2 个空格,并且您只想对函数名称进行排序,请键入
view.run_command("indent_respectful_sort", {"indent": " ", "onlyDepth" : 3})
进入控制台并点击
Enter
。这将仅对函数名称进行排序,同时尊重结构的其余部分。
如果您想使用不同的选项进行排序,您可以参考插件页面https://github.com/mvnural/sublime-indent-respectful-sort以查看更多选项。